Skip to content
Browse files

Added SessionManager_sessionStats()

  • Loading branch information...
1 parent 863d3d6 commit f11ce2fe925949cb43142ed876442056c8cb9168 Caleb James DeLisle committed Sep 20, 2013
View
2 admin/angel/Core.c
@@ -60,6 +60,7 @@
#include "util/log/IndirectLog.h"
#include "util/Security_admin.h"
#include "util/platform/netdev/NetDev.h"
+#include "interface/SessionManager_admin.h"
#include <crypto_scalarmult_curve25519.h>
@@ -366,6 +367,7 @@ int Core_main(int argc, char** argv)
Core_admin_register(myAddr, dt, logger, ipTun, alloc, admin, eventBase);
Security_admin_register(alloc, logger, admin);
IpTunnel_admin_register(ipTun, admin, alloc);
+ SessionManager_admin_register(dt->sessionManager, admin, alloc);
struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
.allocator = alloc,
View
7 crypto/CryptoAuth.c
@@ -1150,3 +1150,10 @@ struct Interface* CryptoAuth_getConnectedInterface(struct Interface* iface)
}
return NULL;
}
+
+struct ReplayProtector* CryptoAuth_getReplayProtector(struct Interface* iface)
+{
+ struct CryptoAuth_Wrapper* wrapper =
+ Identity_cast((struct CryptoAuth_Wrapper*)iface->senderContext);
+ return &wrapper->replayProtector;
+}
View
5 crypto/CryptoAuth.h
@@ -194,4 +194,9 @@ int CryptoAuth_getState(struct Interface* iface);
*/
struct Interface* CryptoAuth_getConnectedInterface(struct Interface* iface);
+/**
+ * Get the structure which is used to protect against packet replay attacks.
+ */
+struct ReplayProtector* CryptoAuth_getReplayProtector(struct Interface* iface);
+
#endif
View
37 crypto/ReplayProtector.h
@@ -15,13 +15,31 @@
#ifndef ReplayProtector_H
#define ReplayProtector_H
-#include <stdint.h>
+#include "util/Bits.h"
+
#include <stdbool.h>
struct ReplayProtector
{
+ /** internal bitfield. */
+ uint64_t bitfield;
+
+ /** Internal offset. */
uint32_t baseOffset;
- uint32_t bitfield;
+
+ /** Number of definite duplicate packets. */
+ uint32_t duplicates;
+
+ /** Number of lost packets. */
+ uint32_t lostPackets;
+
+ /**
+ * Number of packets which could not be verified because they were out of range.
+ * Growing lostPackets and receivedOutOfRange together indicate severe packet
+ * reordering issues.
+ * receivedOutOfRange growing along indicates duplicate packets.
+ */
+ uint32_t receivedOutOfRange;
};
/**
@@ -37,21 +55,24 @@ struct ReplayProtector
static inline bool ReplayProtector_checkNonce(const uint32_t nonce, struct ReplayProtector* context)
{
if (nonce < context->baseOffset) {
+ context->receivedOutOfRange++;
return false;
}
uint32_t offset = nonce - context->baseOffset;
- if (offset > 20) {
- context->baseOffset += offset - 20;
- context->bitfield = ((offset > 51) ? 0 : context->bitfield >> (offset - 20)) | (1 << 20);
- return true;
+ while (offset > 32) {
+ context->baseOffset += 32;
+ context->lostPackets += 32 - Bits_popCountx32(context->bitfield & 0xffffffffu);
+ context->bitfield >>= 32;
+ offset -= 32;
}
- if (context->bitfield & (1 << offset)) {
+ if (context->bitfield & (((uint64_t)1) << offset)) {
+ context->duplicates++;
return false;
}
- context->bitfield |= (1 << offset);
+ context->bitfield |= (((uint64_t)1) << offset);
return true;
}
View
1 crypto/test/Exports.c
@@ -25,6 +25,7 @@
#define CryptoAuth_getState Exports_CryptoAuth_getState
#define CryptoAuth_getConnectedInterface Exports_CryptoAuth_getConnectedInterface
#define CryptoAuth_getUsers Exports_CryptoAuth_getUsers
+#define CryptoAuth_getReplayProtector Exports_CryptoAuth_getReplayProtector
#include "crypto/CryptoAuth.c"
View
2 crypto/test/ReplayProtector_test.c
@@ -24,7 +24,7 @@ int main()
{
uint16_t randomShorts[8192];
uint16_t out[8192];
- struct ReplayProtector rp = {0,0};
+ struct ReplayProtector rp = {.bitfield = 0};
struct Allocator* alloc;
BufferAllocator_STACK(alloc, 1024);
View
1 interface/CMakeLists.txt
@@ -27,6 +27,7 @@ add_library(interface
UDPInterface_admin.c
InterfaceConnector.c
SessionManager.c
+ SessionManager_admin.c
ICMP6Generator.c
MultiInterface.c
FramingInterface.c
View
5 interface/InterfaceController.h
@@ -61,6 +61,11 @@ struct InterfaceController_peerStats
uint64_t switchLabel;
bool isIncomingConnection;
String* user;
+
+ /** Packet loss/duplication statistics. see: ReplayProtector */
+ uint32_t duplicates;
+ uint32_t lostPackets;
+ uint32_t receivedOutOfRange;
};
struct InterfaceController
View
7 interface/InterfaceController_admin.c
@@ -51,6 +51,10 @@ static void adminPeerStats(Dict* args, void* vcontext, String* txid)
String* isIncoming = String_CONST("isIncoming");
String* user = String_CONST("user");
+ String* duplicates = String_CONST("duplicates");
+ String* lostPackets = String_CONST("lostPackets");
+ String* receivedOutOfRange = String_CONST("receivedOutOfRange");
+
List* list = NULL;
for (int counter=0; i < count && counter++ < ENTRIES_PER_PAGE; i++) {
Dict* d = Dict_new(alloc);
@@ -68,6 +72,9 @@ static void adminPeerStats(Dict* args, void* vcontext, String* txid)
Dict_putString(d, switchLabel, String_new((char*)labelStack, alloc), alloc);
Dict_putInt(d, isIncoming, stats[i].isIncomingConnection, alloc);
+ Dict_putInt(d, duplicates, stats[i].duplicates, alloc);
+ Dict_putInt(d, lostPackets, stats[i].lostPackets, alloc);
+ Dict_putInt(d, receivedOutOfRange, stats[i].receivedOutOfRange, alloc);
if (stats[i].isIncomingConnection) {
Dict_putString(d, user, stats[i].user, alloc);
View
12 interface/SessionManager.c
@@ -142,6 +142,18 @@ struct SessionManager_Session* SessionManager_sessionForHandle(uint32_t handle,
return (index == -1) ? NULL : &sm->ifaceMap.values[index];
}
+struct SessionManager_HandleList* SessionManager_getHandleList(struct SessionManager* sm,
+ struct Allocator* alloc)
+{
+ struct SessionManager_HandleList* out =
+ Allocator_malloc(alloc, sizeof(struct SessionManager_HandleList));
+ uint32_t* buff = Allocator_malloc(alloc, 4 * sm->ifaceMap.count);
+ Bits_memcpy(buff, sm->ifaceMap.handles, 4 * sm->ifaceMap.count);
+ out->handles = buff;
+ out->count = sm->ifaceMap.count;
+ return out;
+}
+
struct SessionManager* SessionManager_new(Interface_CALLBACK(decryptedIncoming),
Interface_CALLBACK(encryptedOutgoing),
void* interfaceContext,
View
12 interface/SessionManager.h
@@ -44,6 +44,12 @@ struct SessionManager_Session
uint8_t ip6[16];
};
+struct SessionManager_HandleList
+{
+ uint32_t count;
+ uint32_t* handles;
+};
+
/**
* Create a new session manager for keeping track of and expiring crypto sessions.
* The typical use case is discriminating between packets by ip address, keyOffset is the number
@@ -88,4 +94,10 @@ struct SessionManager_Session* SessionManager_getSession(uint8_t* lookupKey,
struct SessionManager_Session* SessionManager_sessionForHandle(uint32_t handle,
struct SessionManager* sm);
+/**
+ * Get the list of all handles.
+ */
+struct SessionManager_HandleList* SessionManager_getHandleList(struct SessionManager* sm,
+ struct Allocator* alloc);
+
#endif
View
123 interface/SessionManager_admin.c
@@ -0,0 +1,123 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "admin/Admin.h"
+#include "benc/String.h"
+#include "benc/Dict.h"
+#include "benc/List.h"
+#include "crypto/Key.h"
+#include "crypto/ReplayProtector.h"
+#include "interface/SessionManager.h"
+#include "interface/SessionManager_admin.h"
+#include "util/AddrTools.h"
+
+struct Context
+{
+ struct Allocator* alloc;
+ struct SessionManager* sm;
+ struct Admin* admin;
+};
+
+// typical peer record is around 140 benc chars, so can't have very many in 1023
+#define ENTRIES_PER_PAGE 64
+static void getHandles(Dict* args, void* vcontext, String* txid)
+{
+ struct Context* context = vcontext;
+ struct Allocator* alloc = Allocator_child(context->alloc);
+
+ int64_t* page = Dict_getInt(args, String_CONST("page"));
+ uint32_t i = (page) ? *page * ENTRIES_PER_PAGE : 0;
+ struct SessionManager_HandleList* hList = SessionManager_getHandleList(context->sm, alloc);
+
+ List* list = NULL;
+ for (int counter=0; i < hList->count && counter++ < ENTRIES_PER_PAGE; i++) {
+ list = List_addInt(list, hList->handles[i], alloc);
+ }
+
+ Dict* r = Dict_new(alloc);
+ Dict_putList(r, String_CONST("handles"), list, alloc);
+ Dict_putInt(r, String_CONST("total"), hList->count, alloc);
+
+ String* more = String_CONST("more");
+ if (i < hList->count) {
+ Dict_putInt(r, more, 1, alloc);
+ }
+
+ Admin_sendMessage(r, txid, context->admin);
+
+ Allocator_free(alloc);
+}
+
+static void sessionStats2(Dict* args,
+ struct Context* context,
+ struct Allocator* alloc,
+ String* txid)
+{
+ int64_t* handleP = Dict_getInt(args, String_CONST("handle"));
+ uint32_t handle = *handleP;
+
+ struct SessionManager_Session* session = SessionManager_sessionForHandle(handle, context->sm);
+
+ Dict* r = Dict_new(alloc);
+ if (!session) {
+ Dict_putString(r, String_CONST("error"), String_CONST("no such session"), alloc);
+ Admin_sendMessage(r, txid, context->admin);
+ return;
+ }
+
+ struct ReplayProtector* rp = CryptoAuth_getReplayProtector(&session->iface);
+ Dict_putInt(r, String_CONST("duplicates"), rp->duplicates, alloc);
+ Dict_putInt(r, String_CONST("lostPackets"), rp->lostPackets, alloc);
+ Dict_putInt(r, String_CONST("receivedOutOfRange"), rp->receivedOutOfRange, alloc);
+
+ uint8_t* key = CryptoAuth_getHerPublicKey(&session->iface);
+ Dict_putString(r, String_CONST("publicKey"), Key_stringify(key, alloc), alloc);
+ Dict_putInt(r, String_CONST("last"), session->lastMessageTime, alloc);
+ Dict_putInt(r, String_CONST("version"), session->version, alloc);
+ Dict_putInt(r, String_CONST("handle"),
+ Endian_bigEndianToHost32(session->receiveHandle_be), alloc);
+ Dict_putInt(r, String_CONST("sendHandle"),
+ Endian_bigEndianToHost32(session->sendHandle_be), alloc);
+ Admin_sendMessage(r, txid, context->admin);
+ return;
+}
+
+static void sessionStats(Dict* args, void* vcontext, String* txid)
+{
+ struct Context* context = vcontext;
+ struct Allocator* alloc = Allocator_child(context->alloc);
+ sessionStats2(args, context, alloc, txid);
+ Allocator_free(alloc);
+}
+
+void SessionManager_admin_register(struct SessionManager* sm,
+ struct Admin* admin,
+ struct Allocator* alloc)
+{
+ struct Context* ctx = Allocator_clone(alloc, (&(struct Context) {
+ .alloc = alloc,
+ .sm = sm,
+ .admin = admin
+ }));
+
+ Admin_registerFunction("SessionManager_getHandles", getHandles, ctx, true,
+ ((struct Admin_FunctionArg[]) {
+ { .name = "page", .required = 0, .type = "Int" }
+ }), admin);
+
+ Admin_registerFunction("SessionManager_sessionStats", sessionStats, ctx, true,
+ ((struct Admin_FunctionArg[]) {
+ { .name = "handle", .required = 1, .type = "Int" }
+ }), admin);
+}
View
26 interface/SessionManager_admin.h
@@ -0,0 +1,26 @@
+/* vim: set expandtab ts=4 sw=4: */
+/*
+ * You may redistribute this program and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef SessionManager_admin_H
+#define SessionManager_admin_H
+
+#include "admin/Admin.h"
+#include "interface/SessionManager.h"
+#include "memory/Allocator.h"
+
+void SessionManager_admin_register(struct SessionManager* sm,
+ struct Admin* admin,
+ struct Allocator* alloc);
+
+#endif
View
8 net/DefaultInterfaceController.c
@@ -484,8 +484,8 @@ static void populateBeacon(struct InterfaceController* ifc, struct Headers_Beaco
}
static int getPeerStats(struct InterfaceController* ifController,
- struct Allocator* alloc,
- struct InterfaceController_peerStats** statsOut)
+ struct Allocator* alloc,
+ struct InterfaceController_peerStats** statsOut)
{
struct Context* ic = Identity_cast((struct Context*) ifController);
int count = ic->peerMap.count;
@@ -506,6 +506,10 @@ static int getPeerStats(struct InterfaceController* ifController,
if (s->isIncomingConnection) {
s->user = CryptoAuth_getUser(peer->cryptoAuthIf);
}
+ struct ReplayProtector* rp = CryptoAuth_getReplayProtector(peer->cryptoAuthIf);
+ s->duplicates = rp->duplicates;
+ s->lostPackets = rp->lostPackets;
+ s->receivedOutOfRange = rp->receivedOutOfRange;
}
*statsOut = stats;
View
11 net/Ducttape.c
@@ -972,11 +972,11 @@ static uint8_t handleControlMessage(struct Ducttape_pvt* context,
labelStr, Endian_bigEndianToHost16(ctrl->type_be));
}
- if (pong && context->public.switchPingerIf.receiveMessage) {
+ if (pong && context->pub.switchPingerIf.receiveMessage) {
// Shift back over the header
Message_shift(message, Headers_SwitchHeader_SIZE);
- context->public.switchPingerIf.receiveMessage(
- message, &context->public.switchPingerIf);
+ context->pub.switchPingerIf.receiveMessage(
+ message, &context->pub.switchPingerIf);
}
return Error_NONE;
}
@@ -1149,6 +1149,7 @@ struct Ducttape* Ducttape_register(uint8_t privateKey[32],
eventBase,
cryptoAuth,
allocator);
+ context->pub.sessionManager = context->sm;
Bits_memcpyConst(&context->module, (&(struct DHTModule) {
.name = "Ducttape",
@@ -1169,12 +1170,12 @@ struct Ducttape* Ducttape_register(uint8_t privateKey[32],
}
// setup the switch pinger interface.
- Bits_memcpyConst(&context->public.switchPingerIf, (&(struct Interface) {
+ Bits_memcpyConst(&context->pub.switchPingerIf, (&(struct Interface) {
.sendMessage = incomingFromPinger,
.senderContext = context
}), sizeof(struct Interface));
- return &context->public;
+ return &context->pub;
}
void Ducttape_setUserInterface(struct Ducttape* dt, struct Interface* userIf)
View
1 net/Ducttape.h
@@ -27,6 +27,7 @@
struct Ducttape
{
struct Interface switchPingerIf;
+ struct SessionManager* sessionManager;
};
struct Ducttape* Ducttape_register(uint8_t privateKey[32],
View
2 net/Ducttape_pvt.h
@@ -45,7 +45,7 @@ enum Ducttape_SessionLayer {
struct Ducttape_pvt
{
/** the public fields. */
- struct Ducttape public;
+ struct Ducttape pub;
/** The network module for the DHT. */
struct DHTModule module;
View
6 test/cjdroute_routerPing_test.c
@@ -65,20 +65,20 @@ int main()
// bad checksum
udp->checksum_be = 1;
struct Message m = { .bytes = buff+PADDING, .length = buffLen, .padding = PADDING };
- Ducttape_injectIncomingForMe(&m, &dt->public, herPublicKey);
+ Ducttape_injectIncomingForMe(&m, &dt->pub, herPublicKey);
Assert_always(!dt->switchInterface.receiverContext);
// zero checksum
udp->checksum_be = 0;
struct Message m2 = { .bytes = buff+PADDING, .length = buffLen, .padding = PADDING };
- Ducttape_injectIncomingForMe(&m2, &dt->public, herPublicKey);
+ Ducttape_injectIncomingForMe(&m2, &dt->pub, herPublicKey);
Assert_always(!dt->switchInterface.receiverContext);
// good checksum
udp->checksum_be =
Checksum_udpIp6(ip6->sourceAddr, (uint8_t*) udp, strlen(pingBenc) + Headers_UDPHeader_SIZE);
struct Message m3 = { .bytes = buff+PADDING, .length = buffLen, .padding = PADDING };
- Ducttape_injectIncomingForMe(&m3, &dt->public, herPublicKey);
+ Ducttape_injectIncomingForMe(&m3, &dt->pub, herPublicKey);
Assert_always(dt->switchInterface.receiverContext);
Allocator_free(alloc);
View
9 util/Bits.h
@@ -22,6 +22,15 @@
#include <stdint.h>
#include <stddef.h>
+static inline int Bits_popCountx32(uint32_t number)
+{
+ int out = 0;
+ for (int i = 0; i < 32; i++) {
+ out += ((number >> i) & 1);
+ }
+ return out;
+}
+
static inline int Bits_log2x64(uint64_t number)
{
int out = 0;

0 comments on commit f11ce2f

Please sign in to comment.
Something went wrong with that request. Please try again.