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

📄 keyutils.cpp

📁 伯克利做的SFTP安全文件传输协议
💻 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 + -