📄 keyutils.cpp
字号:
// $Archive:: /STP/SafeTP/keyutils.cpp$// $Date: 2000/09/01 22:55:03 $// $Revision: 1.29 $// Description: key storage abstraction - used for storing key pairs// copyright 2000, SafeTP Development Group, Inc. Terms of use are as specified in license.txt.#include <string.h>#include <stdio.h>#include "ssha.h"#include "keyutils.h"#include "crc.h"#include "nonport.h" // limitFileAccess, ensurePath#include "xassert.h" // xfailure#ifdef KEYS_IN_REGISTRY // all win32 projects# ifdef SIMPLE_REGISTRY # include <windows.h># define MAX_REG_PATH 1024# else# include "config.h"# include "registry.h"# include "settings.h"# include "messages.h"# endif#else // unix server and client# include <stdio.h># include "usercfg.h" // userConfigDir# ifdef WIN32# ifndef __BORLANDC__# include <direct.h> // _mkdir()# else# include <dir.h> // mkdir# define _mkdir mkdir# pragma warn -par // unused parameters warning# endif# define DIRSLASH '\\'# else // unix# define DIRSLASH '/'# endif#endif#ifndef FALSE#define FALSE 0#endif#ifndef TRUE#define TRUE 1#endif// This module allows keys to be saved & retrieved from permanent storage,// while abstracting away the actual way they're stored//--------------------------------------------------------------------------#if defined(KEYS_IN_REGISTRY) && defined(SIMPLE_REGISTRY) // sm: 9/18/00 11:14// a helper function for simple registry versionsstatic HKEY openRegKey(const char *pathname, char* valname, bool forceProtectedArea, bool load) { assert(pathname[0] != '/' && pathname[0] != '\\'); HKEY basekey; char fullpath[MAX_REG_PATH]; fullpath[0] = '\0'; strcat(fullpath, SIMPLE_REGISTRY_BASE); if (forceProtectedArea) { strcat(fullpath, "Protected/"); basekey = HKEY_LOCAL_MACHINE; } else basekey = HKEY_CURRENT_USER; strcat(fullpath, pathname); char *pos; for (pos=fullpath; *pos; pos++) if (*pos == '/') *pos = '\\'; // translate slashes pos = strrchr(fullpath, '\\'); // get the value name assert(pos); *pos = '\0'; strcpy(valname, pos+1); int retval; HKEY handle = NULL; if (load) retval = RegOpenKeyEx(basekey, fullpath, NULL, KEY_READ, &handle); else { DWORD disp; retval = RegCreateKeyEx(basekey, fullpath, NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_READ, NULL, &handle, &disp); } return handle; }#endif//--------------------------------------------------------------------------int LoadKey(string& pathname, DataBlock& keydata, bool forceProtectedArea) {// Load a key given the relative pathname, and store it in data// returns TRUE if successful, or FALSE on failure (key not found) #ifdef KEYS_IN_REGISTRY // client- uses registry #ifdef SIMPLE_REGISTRY char valname[MAX_REG_PATH]; HKEY handle = openRegKey(pathname.pcharc(), valname, forceProtectedArea, true); if (!handle) return FALSE; DWORD len = 0; DWORD valtype = 0; int retval; retval = RegQueryValueEx(handle, valname, NULL, &valtype, NULL, &len); if (retval != ERROR_SUCCESS || valtype != REG_BINARY) { RegCloseKey(handle); return FALSE; } keydata.ensureAtLeast(len+2); retval = RegQueryValueEx(handle, valname, NULL, NULL, keydata.getData(), &len); RegCloseKey(handle); if (retval == ERROR_SUCCESS) { keydata.setDataLen(len); return TRUE; } else return FALSE; #else /* win32 client projects */ assert(!strcmp(SIMPLE_REGISTRY_BASE, SFTP_REG_BASE_PATH)); // simple sanity check that needs to be somewhere int keylength; if (forceProtectedArea) { // load from protected region char newpath[MAX_REG_PATH]; strcpy(newpath, "Protected/"); strcat(newpath, pathname.pchar()); int retval = Registry::Load(HKEY_LOCAL_MACHINE, newpath, NULL, &keylength); // get length if (retval != ERROR_SUCCESS) return FALSE; keydata.setAllocated(keylength); retval = Registry::Load(HKEY_LOCAL_MACHINE, newpath, keydata.getData(), &keylength); if (retval != ERROR_SUCCESS) { #if 1 char temp[255]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, retval, NULL, temp, 255, NULL); Message("Failure in LoadKey: second Registry::Load(%s) failed with error %i: %s", newpath, retval, temp); #endif return FALSE; } } else { // load from default user region keylength = Settings::Load(pathname.pchar(), NULL, 0); if (keylength == 0) return FALSE; keydata.setAllocated(keylength); int retval = Settings::Load(pathname.pchar(), (char *)keydata.getData(), keylength); if (!retval) { #if 1 Message("Failure in LoadKey: second Settings::Load(%s) failed.", pathname.pchar()); #endif return FALSE; } } keydata.setDataLen(keylength); return TRUE; #endif #else // server - uses files #ifdef WIN32 // translate slashes for (int i=0; i < pathname.length(); i++) if (pathname.pchar()[i] == '/') pathname.pchar()[i] = '\\'; #endif FILE* fp = fopen(stringb(userConfigDir() << DIRSLASH << pathname).pcharc(), "rb"); if (fp == NULL) { keydata = DataBlock(); return FALSE; // key not found } if (fseek(fp, 0, SEEK_END) != 0) { fclose(fp); keydata = DataBlock(); return FALSE; // seek error } long sz = ftell(fp); if (sz < 0) { fclose(fp); keydata = DataBlock(); return FALSE; // ftell error } if (fseek(fp, 0, SEEK_SET) != 0) { fclose(fp); keydata = DataBlock(); return FALSE; // seek error } keydata.setAllocated(sz); if (fread(keydata.getData(), 1, sz, fp) != (size_t)sz) { fclose(fp); keydata = DataBlock(); return FALSE; } keydata.setDataLen(sz); if (fclose(fp) != 0) { keydata = DataBlock(); return FALSE; // close error } return TRUE; #endif }//--------------------------------------------------------------------------int SaveKey(string& pathname, const DataBlock& keydata, bool forceProtectedArea) {// Save a key to the relative pathname// returns TRUE if successful, or FALSE on failure (disk full, permission problems) #ifdef KEYS_IN_REGISTRY // client- uses registry #ifdef SIMPLE_REGISTRY char valname[MAX_REG_PATH]; HKEY handle = openRegKey(pathname.pcharc(), valname, forceProtectedArea, false); if (!handle) return FALSE; int retval = RegSetValueEx(handle, valname, NULL, REG_BINARY, keydata.getDataC(), keydata.getDataLen()); RegCloseKey(handle); return (retval == ERROR_SUCCESS ? TRUE : FALSE); #else /* win32 client projects */ if (forceProtectedArea) { // save to protected region char newpath[MAX_REG_PATH]; strcpy(newpath, "Protected/"); strcat(newpath, pathname.pchar()); return (Registry::Save(HKEY_LOCAL_MACHINE, newpath, keydata.getDataC(), keydata.getDataLen()) == ERROR_SUCCESS); } else { // save to default user region return Settings::Save(pathname.pchar(), (char *)keydata.getDataC(), keydata.getDataLen()); } #endif #else // server - uses files string fullpathname = stringb(userConfigDir() << DIRSLASH << pathname); #if 0 // this code has been adapted and superceded by what's in nonport; // the code here has at least one bug, in that it starts at index 0 for (int i=0; i < fullpathname.length(); i++) { if (fullpathname[i] == '/' || fullpathname[i] == '\\') { fullpathname[i] = '\0'; createDirectory(fullpathname.pcharc()); // make directory if necessary; automatically limits file access fullpathname[i] = DIRSLASH; } } #else ensurePath(fullpathname, false /*isDirectory*/); #endif FILE* fp = fopen(fullpathname.pcharc(), "wb"); if (fp == NULL) return FALSE; // creation / permission error if (fwrite(keydata.getDataC(), 1, keydata.getDataLen(), fp) != (unsigned int)keydata.getDataLen()) { fclose(fp); return FALSE; // write error } if (fclose(fp) != 0) return FALSE; // close error // these are sensitive files, generally limitFileAccess(fullpathname); return TRUE; #endif }//--------------------------------------------------------------------------int ReformatKey(char *key, bool includeCR) { int sz = strlen(key); char* buffer = new char[sz*2+1]; char* to = buffer, *from = key; int i; for (i=0; i < sz; i++) { *(to++) = *(from++); if (i % KEY_LINE_LENGTH == KEY_LINE_LENGTH - 1) { if (includeCR) *(to++) = '\r'; *(to++) = '\n'; } } if ((i-1) % KEY_LINE_LENGTH != KEY_LINE_LENGTH - 1) { // add final newline if (includeCR) *(to++) = '\r'; *(to++) = '\n'; } *to = '\0'; strcpy(key, buffer); int newlen = to - buffer; delete buffer; return newlen; }//--------------------------------------------------------------------------unsigned long GetKeyChecksum(const unsigned char* data, int len) { #if 1 return crc32(data, len); #else unsigned long ret = 0; for (int i=0; i < len; i++) { ret = (ret << 8 | ((ret >> 24) & 0xFF)) & 0xFFFFFFFF; // 32-bit circular left shift ret ^= data[i]; } return ret; #endif }//--------------------------------------------------------------------------string GetKeyShaString(const DataBlock& key) { // compute sha of key DataBlock sha = Sha1(key); // render it as a hex string int datalen = sha.getDataLen(); string ret(datalen * 3 + 1); for (int i=0; i<datalen; i++) { sprintf(ret.pchar() + i*3, "%02X ", sha.getDataC()[i]); } // trim final space ret[datalen*3] = 0; return ret; }//--------------------------------------------------------------------------#if defined(__WIN32__) && !defined(SIMPLE_REGISTRY) // only on client//--------------------------------------------------------------------------KeySearch::KeySearch(string& searchroot, string& keyname, const DataBlock& keydata) { char buffer[4096]; // pick a ridiculously large buffer so we never run out cnt = Settings::Search(searchroot.pchar(), keyname.pchar(), keydata.getDataC(), keydata.getDataLen(), buffer, 4096); if (cnt == 0) { pathlist = NULL; return; } pathlist = new string*[cnt]; char *p = buffer; for (int i=0; i < cnt; i++) { pathlist[i] = new string; *(pathlist[i]) = p; p += pathlist[i]->length() + 1; } }//--------------------------------------------------------------------------KeySearch::~KeySearch() { if (pathlist) { for (int i=0; i < cnt; i++) delete pathlist[i]; delete pathlist; pathlist = NULL; } }//--------------------------------------------------------------------------void KeySearch::sortentries() { // simple strcmp sort of entries // array is always pretty small, so use a simple selection sort for (int i=0; i < cnt; i++) { int minelem = i; for (int j=i; j < cnt; j++) { if (strcmp(pathlist[j]->pchar(),pathlist[minelem]->pchar())<0) minelem = j; } string* tmp = pathlist[i]; pathlist[i] = pathlist[minelem]; pathlist[minelem] = tmp; } }//--------------------------------------------------------------------------#endif//--------------------------------------------------------------------------DataBlock sm_loadKey(char const *name, bool forceProtectedArea){ string s(name); DataBlock ret; if (!LoadKey(s, ret, forceProtectedArea)) { xfailure(stringb("failed to load key " << name)); } return ret;}void sm_saveKey(char const *name, DataBlock const &block, bool forceProtectedArea){ string temp(name); if (!SaveKey(temp, block, forceProtectedArea)) { xfailure(stringb("failed to save key " << name)); }}bool sm_testKey(char const *name, bool forceProtectedArea){ string s(name); DataBlock ret; return LoadKey(s, ret, forceProtectedArea) != false;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -