⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sfs.cpp

📁 一个用于点对点传输加密的工具包源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2001 Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *   the documentation and/or other materials provided with the *   distribution. * * 3. Neither the name of the Intel Corporation nor the names of its *    contributors may be used to endorse or promote products derived *    from this software without specific prior written permission. *  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. *//* * sfs: Secure File Sharing */#ifdef WIN32#include <windows.h>#else#include <sys/time.h>#include <unistd.h>#endif#include <stdio.h>#include <string.h>#include <stdlib.h>#include <ctype.h>#include <ptp/ptp.h>#include <ptp/id.h>#include <ptp/auth.h>#include <ptp/store.h>#include <ptp/collect.h>#include <ptp/net.h>#include <ptp/key.h>#include <ptp/rand.h>#include <ptp/debug.h>// Uncomment to build for performance testing//#define PERF_TEST 1const char *prog = NULL;#define STRLEN_CONST(x) (sizeof(x) - 1)#define STRNCMP_CONST(x, y) strncmp((x), (y), sizeof(y) - 1)#define SFS_DEFAULT_PORT 8080#define SFS_READ_SIZE 8192#define SFS_FLAGS_ROLL 0x1#define SFS_FLAGS_PLAINTEXT_XFER 0x2#define SFS_AUTH_URL "/auth"#define SFS_RESP_URL "/resp"#define SFS_SEARCH_URL "/search"/* * SFS network protocol * * Authentication: *   HTTP PUT /auth | CERT *   HTTP OK | CHAL | CERT *   HTTP PUT /resp | RESP | CHAL | ENVELOPE(FLAGS) *   HTTP OK | RESP | ENVELOPE(KEYID | SHADOW | KEY) * * Search: *   HTTP PUT /search | KEYID | E(DATA) *   HTTP OK | E(DATA) * * Get: *   HTTP GET /KEYID/FILEID *   HTTP OK | E(DATA) */struct Key:public PTP::List::Entry{	struct Shared	{		BYTE keyid[4];		BYTE shadow[4];		BYTE key[PTP::Key::KEY_SIZE];	};	BYTE id[PTP::Identity::KEY_SIZE];	PTP::Net::Ip ip;	PTP::Net::Port port;	unsigned long keyid;	unsigned long shadow;	int flags;	Shared shared;};struct Response:public PTP::List::Entry{	int id;	char *name;	char *url;};struct TransferContext{	TransferContext(PTP::Net::Connection *conn, FILE *filep)		:c(conn), fp(filep) {}	PTP::Net::Connection *c;	FILE *fp;};static Key *FindKey(PTP::List *keys,	const PTP::Identity *ident,	PTP::Net::Ip ip,	PTP::Net::Port port){	BYTE id[PTP::Identity::KEY_SIZE];	if (ident)		ident->GetKey(id);	Key *key = NULL;	keys->Lock();	PTP_LIST_FOREACH(Key, key, keys)	{		if (key->ip == ip		    && key->port == port		    && (!ident || memcmp(key->id, id, sizeof(id)) == 0))			break;	}	keys->Unlock();	return key;}static Key *CreateKey(PTP::List *keys, const PTP::Identity *id, PTP::Net::Ip ip, int flags){	static unsigned long keyid = 0;	Key *key = FindKey(keys, id, ip, 0);	if (!key)	{		key = new Key;		id->GetKey(key->id);		key->ip = ip;		key->port = 0;		key->keyid = 0;		keys->Insert(key);		flags |= SFS_FLAGS_ROLL;	}	if (flags & SFS_FLAGS_ROLL)	{		key->keyid = keyid++;		PTP::Net::Set32(key->shared.keyid, key->keyid);		PTP::Random::Fill((BYTE*) &key->shadow, sizeof(key->shadow));		PTP::Net::Set32(key->shared.shadow, key->shadow);		PTP::Random::Fill(key->shared.key, sizeof(key->shared.key));		unsigned long shadow2 = 0;		PTP::Random::Fill((BYTE*) &shadow2, sizeof(shadow2));		key->shadow ^= shadow2;	}	key->flags = (flags & ~SFS_FLAGS_ROLL);		return key;}static Key *ImportKey(PTP::List *keys,	  const PTP::Identity *id,	  PTP::Net::Ip ip,	  PTP::Net::Port port,	  int flags,	  const Key::Shared *shared){	Key *key = FindKey(keys, id, ip, port);	if (!key)	{		key = new Key;		id->GetKey(key->id);		key->ip = ip;		key->port = port;		key->keyid = PTP::Net::Get32(shared->keyid);		key->shadow = PTP::Net::Get32(shared->shadow);		memcpy(&key->shared, shared, sizeof(key->shared));		keys->Insert(key);	}	else	{		key->keyid = PTP::Net::Get32(shared->keyid);		key->shadow = PTP::Net::Get32(shared->shadow);		memcpy(&key->shared, shared, sizeof(key->shared));	}	key->flags = (flags & ~SFS_FLAGS_ROLL);	return key;}static Key *FindKey(PTP::List *keys, unsigned long keyid){	Key *key = NULL;	keys->Lock();	PTP_LIST_FOREACH(Key, key, keys)	{		if (key->keyid == keyid)			break;	}	keys->Unlock();	return key;}static voidDestroyKeys(PTP::List *keys){	Key *key = NULL;	keys->Lock();	PTP_LIST_FOREACH(Key, key, keys)	{		keys->Remove(key, 0);		delete key;	}	keys->Unlock();}static intInsertResponse(PTP::List *resps, int *count, char *start, char **end){	start = strstr(start, "HREF=\"");	if (!start)		return -1;	start += STRLEN_CONST("HREF=\"");	char *e = strchr(start, '"');	if (!e)		return -1;	int size = e - start;	char *url = new char[size + 1];	memcpy(url, start, size);	url[size] = '\0';	start = e + 2;	e = strchr(start, '<');	if (!e)	{		delete [] url;		return -1;	}	size = e - start;	char *name = new char[size + 1];	memcpy(name, start, size);	name[size] = '\0';	Response *resp = new Response;	(*count)++;	resp->id = *count;	resp->name = name;	resp->url = url;	resps->Append(resp);	if (end)		*end = e + 1;	return 0;}static Response *FindResponse(PTP::List *resps, int id){	Response *resp;	resps->Lock();	PTP_LIST_FOREACH(Response, resp, resps)	{		if (resp->id == id)			break;	}	resps->Unlock();	return resp;}static voidShowResponses(PTP::List *resps, int showid){	resps->Lock();	Response *resp;	PTP_LIST_FOREACH(Response, resp, resps)	{		printf("  ");		if (showid)			printf("%d) ", resp->id);		printf("%s (%s)\n", resp->name, resp->url);	}	resps->Unlock();}static voidDestroyResponses(PTP::List *resps){	resps->Lock();	Response *resp;	PTP_LIST_FOREACH(Response, resp, resps)	{		resps->Remove(resp, 0);		delete [] resp->name;		delete [] resp->url;		delete resp;	}	resps->Unlock();}static PTP::Net::Connection *Connect(const char *url){	PTP::Net::Port port;	PTP::Net::Ip ip = PTP::Net::Lookup(url, &port, SFS_DEFAULT_PORT);	if (!ip || !port)	{		printf("%s: invalid host `%s'.\n", prog, url);		return NULL;	}	PTP::Net::Connection *c		= new PTP::Net::Connection(PTP::Net::Connection::HTTP,					   ip,					   port);	if (c->Open())	{		printf("%s: connection to `%s' failed.\n", prog, url);		delete c;		return NULL;	}	return c;}static intInsert(PTP::Store *store, PTP::Identity *id){	PTP::Identity *local = store->Find(NULL, 1);	if (local && strcmp(local->GetName(), id->GetName()) == 0)		return 0;	PTP::Identity *issuer = id;	if (id && strcmp(id->GetName(), id->GetIssuerName()) != 0)		issuer = store->Find(id->GetIssuerName());	if (!issuer || issuer->Verify(id) != 0)		return -1;	PTP::Identity *old = store->Find(id->GetName(), 0);	if (old)		store->Remove(old);	store->Insert(id, 0);	store->Save();	return 0;}static Key *Auth(PTP::Store *store, PTP::List *keys, PTP::Net::Connection *c, int flags){	if (!c)		return NULL;	Key *key = FindKey(keys, NULL, c->GetIp(), c->GetPort());	if (key)		return key;	const PTP::Identity *localId = store->Find(NULL, 1);	int size = PTP::Store::Export(localId, 0, NULL, NULL, NULL);	BYTE *buffer = new BYTE[size];	PTP::Store::Export(localId, 0, NULL, NULL, buffer);	int st = c->WriteHttp("PUT", SFS_AUTH_URL, NULL, buffer, NULL, size);	delete [] buffer;	if (st)	{		c->Close();		return NULL;	}	buffer = c->ReadHttp(NULL, -1, NULL, &size);	c->Close();	if (!buffer || size <= PTP::Authenticator::CHALLENGE_SIZE)	{		delete [] buffer;		return NULL;	}	BYTE chal[PTP::Authenticator::CHALLENGE_SIZE];	memcpy(chal, buffer, sizeof(chal));	PTP::Identity *remoteId = PTP::Store::Import(		buffer + sizeof(chal),		size - sizeof(chal),		NULL,		NULL);	delete [] buffer;	if (!remoteId || Insert(store, remoteId))	{		delete remoteId;		return NULL;	}	BYTE fl = (BYTE) flags;	size = PTP::Store::ExportEnvelope(		&fl,		sizeof(fl),		NULL,		remoteId,		localId);	size += (PTP::Authenticator::RESPONSE_SIZE		 + PTP::Authenticator::CHALLENGE_SIZE);	buffer = new BYTE[size];	PTP::Authenticator auth(store);	auth.Respond(chal, buffer);	auth.Challenge(remoteId,		       60,		       (void*) remoteId,		       buffer + PTP::Authenticator::RESPONSE_SIZE);	PTP::Store::ExportEnvelope(		&fl,		sizeof(fl),		buffer		+ PTP::Authenticator::RESPONSE_SIZE		+ PTP::Authenticator::CHALLENGE_SIZE,		remoteId,		localId);	st = c->WriteHttp("PUT", SFS_RESP_URL, NULL, buffer, NULL, size);	delete [] buffer;	if (st)	{		c->Close();		delete remoteId;		return NULL;	}	buffer = c->ReadHttp(NULL, -1, NULL, &size);	c->Close();	if (!buffer	    || size <= PTP::Authenticator::RESPONSE_SIZE	    || auth.Verify(buffer) != remoteId	    || PTP::Store::ImportEnvelope(		    buffer + PTP::Authenticator::RESPONSE_SIZE,		    size - PTP::Authenticator::RESPONSE_SIZE,		    buffer,		    localId,		    remoteId) != sizeof(Key::Shared))	{		delete [] buffer;		delete remoteId;		return NULL;	}	key = ImportKey(keys,			remoteId,			c->GetIp(),			c->GetPort(),			flags,			(const Key::Shared*) buffer);	delete [] buffer;	delete remoteId;	if (!key)		return NULL;	return key;}static intHandleAuth(PTP::Store *store,	   PTP::Authenticator *auth,	   PTP::List *keys,	   PTP::Net::Connection *c){		int size = 0;	BYTE *buffer = c->ReadHttp(NULL, -1, NULL, &size);	if (!buffer)		return -1;	const PTP::Identity *localId = store->Find(NULL, 1);	PTP::Identity *remoteId		= PTP::Store::Import(buffer, size, NULL, NULL);	delete [] buffer;	if (!remoteId)	{		c->Close();		return -1;	}		size = PTP::Authenticator::CHALLENGE_SIZE;	size += PTP::Store::Export(localId, 0, NULL, NULL, NULL);		buffer = new BYTE[size];	auth->Challenge(remoteId, 60, (void*) remoteId,	buffer);	PTP::Store::Export(		localId,		0,		NULL,		NULL,		buffer + PTP::Authenticator::CHALLENGE_SIZE);		int st = c->WriteHttp(PTP::Net::HTTP_OK, NULL, buffer, NULL, size);	delete [] buffer;	c->Close();	if (st)		return -1;	return 0;}static intHandleResp(PTP::Store *store,	   PTP::Authenticator *auth,	   PTP::List *keys,	   PTP::Net::Connection *c){		int size = 0;	BYTE *buffer = c->ReadHttp(NULL, -1, NULL, &size);	if (!buffer)		return -1;	int esize = (size		     - PTP::Authenticator::RESPONSE_SIZE		     - PTP::Authenticator::CHALLENGE_SIZE);	if (esize <= 0)	{		delete [] buffer;		return -1;	}		const PTP::Identity *localId = store->Find(NULL, 1);	PTP::Identity *remoteId		= (PTP::Identity*) auth->Verify(buffer);	if (!remoteId)	{		delete [] buffer;		return -1;	}	BYTE resp[PTP::Authenticator::RESPONSE_SIZE];	memcpy(resp, buffer, sizeof(resp));	BYTE chal[PTP::Authenticator::CHALLENGE_SIZE];	memcpy(chal, buffer + sizeof(resp), sizeof(chal));	BYTE fl;	if (PTP::Store::ImportEnvelope(		buffer + (size - esize),		esize,		&fl,		localId,		remoteId) != sizeof(fl))	{		delete remoteId;		delete [] buffer;		return -1;	}	int flags = (int) fl;	delete [] buffer;		Key *key = CreateKey(keys, remoteId, c->GetIp(), flags);	if (!key)		return -1;		size = PTP::Store::ExportEnvelope(		(BYTE*) &key->shared,		sizeof(key->shared),		NULL,		remoteId,		localId);	size += PTP::Authenticator::RESPONSE_SIZE;	buffer = new BYTE[size];	auth->Respond(chal, buffer);	PTP::Store::ExportEnvelope(		(BYTE*) &key->shared,		sizeof(key->shared),		buffer + PTP::Authenticator::RESPONSE_SIZE,		remoteId,		localId);	delete remoteId;	int st = c->WriteHttp(PTP::Net::HTTP_OK, NULL, buffer, NULL, size);	delete [] buffer;	c->Close();		if (st)		return -1;	return 0;}static intSearch(PTP::Net::Connection *c, Key *key, const char *str, PTP::List *resps){	DestroyResponses(resps);	PTP::Key k(key->shared.key);	int size = k.Encrypt(NULL, strlen(str), NULL);	if (size <= 0)		return -1;	size += 4;	BYTE *buffer = new BYTE[size];	memcpy(buffer, key->shared.keyid, 4);	k.Encrypt((const BYTE*) str, strlen(str), buffer + 4);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -