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

📄 record.c

📁 keyring是一种用于保护PALM中关键信息的系统
💻 C
字号:
/* -*- c-file-style: "java"; -*- * * $Header: /cvsroot/gnukeyring/keyring/record.c,v 1.20 2006/01/13 14:09:04 hoenicke Exp $ *  * Keyring -- store passwords securely on a handheld * Copyright (C) 1999, 2000, 2001 Martin Pool <mbp@users.sourceforge.net> * Copyright (C) 2002-2005 Jochen Hoenicke <hoenicke@users.sourceforge.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *//* * TODO: Check that the terminating NULs in the strings are accounted * for correctly. * * TODO: Is it possible we could be overflowing the stack? */#include "includes.h"extern void *alloca(unsigned long size);typedef struct {    UInt16    version;    UInt8     nameLen;    UInt8     fontID;} PackedKeyType;typedef struct {    UInt16    len;    UInt8     labelID;    UInt8     fontID;} PackedFieldType;#define EVEN(x) (((x)+1)&~1)#define ENDMARKER 0xffffErr Record_Unpack(MemHandle record, UnpackedKeyType **u, CryptoKey *recordKey){    void          *recPtr;    void          *plainBuf, *plainPtr;    UInt8         ivec[recordKey->blockSize];    UInt32        size, cryptSize;    UInt16        fieldLen;    UInt16        offset;    UInt16        fieldCnt;    recPtr = MemHandleLock(record);    ErrFatalDisplayIf(!recPtr, "couldn't lock record");    fieldLen = EVEN(* (UInt16 *) recPtr) + sizeof(FieldHeaderType);    if ((UInt32)fieldLen + recordKey->blockSize > MemHandleSize(record)) {        FrmCustomAlert(KeyDatabaseAlert,                       "record underflow", __FUNCTION__, "");	MemHandleUnlock(record);	return dmErrCorruptDatabase;    }        size = MemHandleSize(record) - recordKey->blockSize;    plainBuf = MemPtrNew(size);    if (plainBuf == NULL) {	MemHandleUnlock(record);	return memErrNotEnoughSpace;    }    plainPtr = plainBuf;    MemMove(plainPtr, recPtr, fieldLen);    plainPtr += fieldLen;    recPtr   += fieldLen;    offset    = fieldLen;    MemMove(ivec, recPtr, recordKey->blockSize);    recPtr += recordKey->blockSize;    cryptSize = (size - fieldLen) & ~(recordKey->blockSize - 1);    if (cryptSize)	CryptoRead(recPtr, plainPtr, cryptSize, recordKey, ivec);    /* Now count the fields */    fieldCnt = 1;    while (*(UInt16 *) plainPtr != ENDMARKER) {	fieldLen = EVEN (*(UInt16 *) plainPtr) + sizeof(FieldHeaderType);	if (offset + fieldLen + 2 > size) {	    FrmCustomAlert(KeyDatabaseAlert,			   "record underflow", __FUNCTION__, "");	    *(UInt16 *)plainPtr = ENDMARKER;	    break;	}	plainPtr += fieldLen;	offset   += fieldLen;   	fieldCnt++;    }    *u = MemPtrNew(sizeof(UnpackedKeyType) + (fieldCnt -1) *sizeof(UInt16));    if (*u == NULL) {	MemWipe(plainBuf, size);	MemPtrFree(plainBuf);	MemHandleUnlock(record);	return memErrNotEnoughSpace;    }    (*u)->numFields = fieldCnt;    (*u)->plainText = plainBuf;    plainPtr = plainBuf;    fieldCnt = 0;    offset = 0;    while (*(UInt16 *) plainPtr != ENDMARKER) {	(*u)->fieldOffset[fieldCnt++] = offset;	fieldLen = EVEN (*(UInt16 *) plainPtr) + sizeof(FieldHeaderType);	plainPtr += fieldLen;	offset   += fieldLen;    }    MemHandleUnlock(record);    return 0;}/* * Basic procedure to save a record: * * setup record: *   calculate the required record length *   resize record to the required length * lock record * write plaintext name * write body: *   allocate a temporary buffer equal to the encrypted-part length *   write the unencoded form into the temporary buffer *   allocate a temporary encryption buffer *   one block at a time, encrypt and write into the database *   release temporary buffer * unlock record * set record position */void Record_SaveRecord(UnpackedKeyType const *unpacked, UInt16 idx, 		       CryptoKey *recordKey){    MemHandle recHandle;    void      *plainPtr, *recPtr;    UInt8     *cryptPtr;    UInt16    nameLen, lastOffset, size, bodySize, packSize;    UInt8     ivec[recordKey->blockSize];    UInt16    i, attr;        plainPtr = unpacked->plainText;    /* Calculate size */    lastOffset = unpacked->fieldOffset[unpacked->numFields-1];    nameLen  = EVEN(*(UInt16*)plainPtr) + sizeof(FieldHeaderType);    bodySize = lastOffset + sizeof(FieldHeaderType)	+ EVEN(*(UInt16*)(plainPtr+lastOffset)) + 2 - nameLen;    packSize = (bodySize + recordKey->blockSize - 1)	& ~(recordKey->blockSize - 1);    size     = nameLen + recordKey->blockSize + packSize;    recHandle = DmResizeRecord(gKeyDB, idx, size);    if (!recHandle) {	UI_ReportSysError2(KeyDatabaseAlert, DmGetLastErr(),                           __FUNCTION__);	return;    }    recPtr = MemHandleLock(recHandle);    for (i = 0; i < recordKey->blockSize; i++) 	ivec[i] = Secrand_GetByte();    DmWrite (recPtr, 0, plainPtr, nameLen);    DmWrite (recPtr, nameLen, ivec, recordKey->blockSize);    cryptPtr = alloca(packSize);    MemMove(cryptPtr, plainPtr + nameLen, bodySize);    for (i = bodySize; i < packSize; i++)	cryptPtr[i] = Secrand_GetByte();    CryptoWrite(cryptPtr, cryptPtr, packSize, recordKey, ivec);    DmWrite(recPtr, nameLen + recordKey->blockSize, cryptPtr, packSize);    MemHandleUnlock(recHandle);    if (DmRecordInfo(gKeyDB, idx, &attr, NULL, NULL) == 0) {	attr = (attr & ~dmRecAttrCategoryMask) | unpacked->category;	DmSetRecordInfo(gKeyDB, idx, &attr, NULL);    }}/* * Frees record and all associated data.  Also overwrites everything * with zeros. */void Record_Free(UnpackedKeyPtr u){    if (u->plainText) {	MemWipe(u->plainText, MemPtrSize(u->plainText));	MemPtrFree(u->plainText);    }    MemWipe(u, MemPtrSize(u));    MemPtrFree(u);}Err Record_SetField(UnpackedKeyPtr record, UInt16 idx, 		    void *data, UInt16 len) {    UInt8 *dest;    UInt16 i;    FieldHeaderType *fldHeader;    UInt16 fldLen;    fldHeader = (FieldHeaderType *)	(record->plainText + record->fieldOffset[idx]);    fldLen = fldHeader->len;    if (EVEN(len) != EVEN(fldLen)) {	/* Resize record */	int diff = EVEN(len) - EVEN(fldLen);	UInt16 oldSize  = MemPtrSize(record->plainText);	UInt16 offset;	void *newText   = MemPtrNew(oldSize + diff);	if (!newText)	    return memErrNotEnoughSpace;	offset = record->fieldOffset[idx] + sizeof(FieldHeaderType);	MemMove(newText, record->plainText, offset);	MemMove(newText + offset + EVEN(len),		record->plainText + offset + EVEN(fldLen),		oldSize - offset - EVEN(fldLen));	for (i = idx + 1; i < record->numFields; i++)	    record->fieldOffset[i] += diff;	MemWipe(record->plainText, oldSize);	MemPtrFree(record->plainText);	record->plainText = newText;	fldHeader = (FieldHeaderType *)	    (record->plainText + record->fieldOffset[idx]);    }    fldHeader->len = len;    dest = (UInt8*) (record->plainText		     + record->fieldOffset[idx]		     + sizeof(FieldHeaderType));    MemMove(dest, data, len);    /* pad with zero */    if ((len & 1))	dest[len] = 0;    return 0;}/* * Write just a single NUL to keep space for this record.  It's not * marked dirty yet -- that'll happen when some real data is written * in. */Err KeyDB_CreateNew(UInt16 *idx){    MemHandle	recHandle;    Char        *ptr;    Err         err;        *idx = dmMaxRecordIndex;    recHandle = DmNewRecord(gKeyDB, idx, 1);    if (!recHandle)         goto findErrOut;    ptr = MemHandleLock(recHandle);    if (!ptr)        goto findErrOut;        if ((err = DmWrite(ptr, 0, "", 1)))        goto errOut;        MemHandleUnlock(recHandle);        return 0;     findErrOut:    err = DmGetLastErr(); errOut:    UI_ReportSysError2(KeyDatabaseAlert, err, __FUNCTION__);    return err;}void Key_SetCategory(UInt16 idx, UInt16 category){    UInt16 attr;    Err err;        if ((err = DmRecordInfo(gKeyDB, idx, &attr, NULL, NULL)))	goto fail;        attr = (attr & ~dmRecAttrCategoryMask) | category;    if ((err = DmSetRecordInfo(gKeyDB, idx, &attr, NULL)))	goto fail;         return;    fail:    UI_ReportSysError2(KeyDatabaseAlert, err, __FUNCTION__);}

⌨️ 快捷键说明

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