feisty meow concerns codebase  2.140
encryption_tentacle.cpp
Go to the documentation of this file.
1 /*****************************************************************************\
2 * *
3 * Name : encryption_tentacle *
4 * Author : Chris Koeritz *
5 * *
6 *******************************************************************************
7 * Copyright (c) 2004-$now By Author. This program is free software; you can *
8 * redistribute it and/or modify it under the terms of the GNU General Public *
9 * License as published by the Free Software Foundation; either version 2 of *
10 * the License or (at your option) any later version. This is online at: *
11 * http://www.fsf.org/copyleft/gpl.html *
12 * Please send any updates to: fred@gruntose.com *
13 \*****************************************************************************/
14 
15 #include "encryption_tentacle.h"
16 #include "encryption_wrapper.h"
17 #include "key_repository.h"
18 
19 #include <crypto/blowfish_crypto.h>
20 #include <crypto/rsa_crypto.h>
23 #include <textual/byte_formatter.h>
24 
25 using namespace basis;
26 using namespace crypto;
27 using namespace loggers;
28 using namespace structures;
29 using namespace textual;
30 
31 namespace octopi {
32 
33 #undef LOG
34 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
35 
36 #define DEBUG_ENCRYPTION_TENTACLE
37  // uncomment for noisier code.
38 
40 
41 encryption_tentacle::encryption_tentacle()
43  (encryption_infoton::encryption_classifier(), false),
44  _server_side(true),
45  _keys(new key_repository),
46  _rsa_private(NULL_POINTER)
47 {
48 }
49 
52  (encryption_infoton::encryption_classifier(), false),
53  _server_side(false),
54  _keys(new key_repository),
55  _rsa_private(new rsa_crypto(private_key))
56 {
57 }
58 
61  (encryption_infoton::encryption_classifier(), false),
62  _server_side(false),
63  _keys(new key_repository),
64  _rsa_private(new rsa_crypto(key_size))
65 {
66 }
67 
69 {
70  WHACK(_rsa_private);
71  WHACK(_keys);
72 }
73 
74 key_repository &encryption_tentacle::keys() const { return *_keys; }
75 
77 { return *_rsa_private; }
78 
80  byte_array &packed_form, infoton * &reformed)
81 {
82  if (classifier != encryption_infoton::encryption_classifier())
83  return NO_HANDLER;
84 
85  return reconstituter(classifier, packed_form, reformed,
87 }
88 
90 {
92 //we need a better approach. it seems there are places where an entity
93 //can get reused and it still expects its key to be present.
94 }
95 
97  const octopus_request_id &item_id, byte_array &transformed)
98 {
99  FUNCDEF("consume");
100  transformed.reset();
101  encryption_infoton *inf = dynamic_cast<encryption_infoton *>(&to_chow);
102  if (!inf) {
103  // this package is not explicitly an encryption infoton. we need to
104  // decrypt it using what we already know.
105 
106  encryption_wrapper *wrap = dynamic_cast<encryption_wrapper *>(&to_chow);
107  if (!wrap) {
108 #ifdef DEBUG_ENCRYPTION_TENTACLE
109 // LOG(astring("got a stray infoton that was not encrypted: ")
110 // + to_chow.text_form());
111 #endif
112  // this signals that we were expecting an encrypted package.
113  return ENCRYPTION_MISMATCH;
114  }
115 
116  octenc_key_record record;
117  octenc_key_record *rec = _keys->lock(item_id._entity);
118  if (!rec) {
119 #ifdef DEBUG_ENCRYPTION_TENTACLE
120  LOG(astring("no key stored for entity ")
121  + item_id._entity.mangled_form()
122  + "; rejecting packet.");
123 #endif
124  return DISALLOWED;
125  }
126  record = *rec;
127  _keys->unlock(rec);
128 
129  byte_array decro;
130  bool decrypts_properly = record._key.decrypt(wrap->_wrapped, decro);
131  if (decrypts_properly) {
132  // this package seems to be intact. we need to reconstitute the
133  // original infoton.
134  transformed = decro; // set the decrypted blob.
135  return PARTIAL;
136  }
137 
138 #ifdef DEBUG_ENCRYPTION_TENTACLE
139  LOG(astring("denying client ") + item_id._entity.mangled_form()
140  + " due to erroneous decryption");
141 #endif
142 
143  // the infoton's client is not authorized; it needs to be dropped.
144  return DISALLOWED;
145  }
146 
147  // reaching here means this is explicitly an encryption startup request.
148 
149  if (!_server_side) {
150  // client's side must track the key we were given for decryption. we'll
151  // use that from now on.
152  blowfish_crypto new_key(blowfish_crypto::minimum_key_size()); // bogus.
153  outcome ret = inf->extract_response(*_rsa_private, new_key);
154  if (ret != OKAY) {
155 #ifdef DEBUG_ENCRYPTION_TENTACLE
156  LOG(astring("client failed to process encrypted blowfish key for ")
157  + item_id._entity.mangled_form());
158 #endif
159  } else {
160  _keys->add(item_id._entity, new_key); // add our key for this guy.
161  }
162  // we do not store a copy of the infoton; it's just done now.
163  return ret;
164  } else {
165  // server's side need to process a key request and send it back using
166  // the public key the requester provided.
167  blowfish_crypto agreed_key(blowfish_crypto::minimum_key_size());
168  // initialized with junk.
169  outcome worked = inf->prepare_blowfish_key(agreed_key);
170  if (worked != OKAY) {
171 #ifdef DEBUG_ENCRYPTION_TENTACLE
172  LOG(astring("server failed to encrypt blowfish key for ")
173  + item_id._entity.mangled_form());
174 #endif
175  } else {
176  _keys->add(item_id._entity, agreed_key); // add our key for this guy.
177  }
178  }
179 
180  if (!store_product(dynamic_cast<infoton *>(inf->clone()), item_id))
181  return NO_SPACE;
182  return OKAY;
183 }
184 
185 } //namespace.
186 
void reset(int number=0, const contents *initial_contents=NULL_POINTER)
Resizes this array and sets the contents from an array of contents.
Definition: array.h:349
Provides a dynamically resizable ASCII character string.
Definition: astring.h:35
A very common template for a dynamic array of bytes.
Definition: byte_array.h:36
Outcomes describe the state of completion for an operation.
Definition: outcome.h:31
Provides BlowFish encryption on byte_arrays using the OpenSSL package.
bool decrypt(const basis::byte_array &source, basis::byte_array &target) const
decrypts the "target" array from the encrypted "source" array.
Supports public key encryption and decryption.
Definition: rsa_crypto.h:33
Encapsulates the chit-chat necessary to establish an encrypted connection.
basis::outcome extract_response(const crypto::rsa_crypto &private_key, crypto::blowfish_crypto &new_key) const
used by the client to extract the shared blowfish key from the server.
basis::outcome prepare_blowfish_key(crypto::blowfish_crypto &new_key)
performs the server side's job on the current key.
virtual clonable * clone() const
must be provided to allow creation of a copy of this object.
static const structures::string_array & encryption_classifier()
returns the classifier for this type of infoton.
virtual void expunge(const octopus_entity &to_remove)
throws out any keys we were maintaining for this entity.
key_repository & keys() const
provides access to our list of keys.
const crypto::rsa_crypto & private_key() const
provides access to the key held here.
virtual basis::outcome consume(infoton &to_chow, const octopus_request_id &item_id, basis::byte_array &transformed)
the base class handles the processing of the request in "to_chow".
encryption_tentacle()
this tentacle will implement the server side.
virtual basis::outcome reconstitute(const structures::string_array &classifier, basis::byte_array &packed_form, infoton *&reformed)
recreates a "reformed" infoton from a packed form.
Wraps an encrypted infoton when the octopus is in an encrypted mode.
basis::byte_array _wrapped
the encrypted data that's held here.
An infoton is an individual request parcel with accompanying information.
Definition: infoton.h:32
void unlock(octenc_key_record *to_unlock)
drops the lock on the key record in "to_unlock".
basis::outcome add(const octopus_entity &ent, const crypto::blowfish_crypto &key)
adds a "key" for the "ent". this will fail if one is already listed.
octenc_key_record * lock(const octopus_entity &ent)
locates the key for "ent", if it's stored.
Tracks the keys that have been assigned for a secure channel.
crypto::blowfish_crypto _key
used for communicating with an entity.
Provides a way of identifying users of an octopus object.
Definition: entity_defs.h:35
basis::astring mangled_form() const
returns the combined string form of the identifier.
Identifies requests made on an octopus by users.
Definition: entity_defs.h:114
octopus_entity _entity
the entity.
Definition: entity_defs.h:116
provides prefab implementations for parts of the tentacle object.
bool store_product(infoton *product, const octopus_request_id &original_id)
used by tentacles to store the objects they produce from infotons.
Definition: tentacle.cpp:118
@ PARTIAL
processing of request is partially done.
Definition: tentacle.h:74
@ ENCRYPTION_MISMATCH
there is a disconnect regarding encryption.
Definition: tentacle.h:75
@ NO_HANDLER
no handler for that type of infoton.
Definition: tentacle.h:73
An array of strings with some additional helpful methods.
Definition: string_array.h:32
#define formal(parameter)
This macro just eats what it's passed; it marks unused formal parameters.
Definition: definitions.h:48
#define NULL_POINTER
The value representing a pointer to nothing.
Definition: definitions.h:32
#define LOG(s)
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition: enhance_cpp.h:57
The guards collection helps in testing preconditions and reporting errors.
Definition: array.h:30
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
Definition: functions.h:121
A logger that sends to the console screen using the standard output device.
basis::outcome reconstituter(const structures::string_array &classifier, basis::byte_array &packed_form, infoton *&reformed, contents *formal(junk))
< reconstituter should work for most infotons to restore flattened infotons.
A dynamic container class that holds any kind of object via pointers.
Definition: amorph.h:55