/************************************************************************** * Function: generateAccountHash * Description: returns the unique hash for the account. * ************************************************************************/ md_hash * generateAccountHash (Account * acct) { static md_hash ret; unsigned char * hashable; int data_length = 0, string_length = 0; MemSet(ret, sizeof(md_hash), 0); /* username, password, acct mod date, * pw mod date, and 256 bits of randomness */ data_length = StrLen(acct->username)+ StrLen(acct->system)+ StrLen(acct->password)+ StrLen(acct->service)+ StrLen(acct->comment)+ sizeof(acct->account_mod_date)+ sizeof(acct->password_mod_date)+ (sizeof(Int16)*16)+1; if((hashable=MemPtrNew(data_length))) { MemSet(hashable, data_length, 0); StrCopy(hashable, acct->username); string_length+=StrLen(acct->username); StrCat(hashable, acct->system); string_length+=StrLen(acct->system); StrCat(hashable, acct->password); string_length+=StrLen(acct->password); StrCat(hashable, acct->service); string_length+=StrLen(acct->service); StrCat(hashable, acct->comment); string_length+=StrLen(acct->comment); MemMove(hashable+string_length, &acct->account_mod_date, sizeof(acct->account_mod_date)); string_length+=sizeof(acct->account_mod_date); MemMove(hashable+string_length, &acct->password_mod_date, sizeof(acct->password_mod_date)); string_length+=sizeof(acct->password_mod_date); /* move some randomness onto the end * to make dictionary attacks impossible. */ random_bytes(hashable+string_length, 32); string_length+=32; md_block(hashable, string_length, ret); MemPtrFree(hashable); } return &ret; }
static int clear_metadata(struct md *md, const char *device) { struct era_superblock *sb; int supported = 0; int valid = 0; sb = md_block(md, MD_NOCRC, 0, 0); if (!sb) return -1; if (le32toh(sb->magic) == SUPERBLOCK_MAGIC) { uint32_t csum; csum = crc_update(crc_init(), &sb->flags, MD_BLOCK_SIZE - sizeof(uint32_t)); csum ^= SUPERBLOCK_CSUM_XOR; if (le32toh(sb->csum) == csum) { valid++; if (le32toh(sb->version) >= MIN_ERA_VERSION && le32toh(sb->version) <= MIN_ERA_VERSION) supported++; } } if (!force && memcmp(sb, empty_block, MD_BLOCK_SIZE)) { char *what; if (valid) { if (supported) what = "valid era superblock"; else what = "unsupported era superblock"; } else what = "existing data"; error(0, "%s found on %s", what, device); return -1; } if (md_write(md, 0, empty_block)) return -1; return 0; }
int era_open(int argc, char **argv) { char table[64], uuid[64]; char *name, *meta, *data, *orig; unsigned orig_major, orig_minor; unsigned meta_major, meta_minor; unsigned data_major, data_minor; struct era_dm_info orig_info; struct era_superblock *sb; uint32_t nr_blocks; uint64_t sectors; unsigned chunks; struct md *md; int chunk; int fd; /* * check and save arguments */ switch (argc) { case 0: error(0, "device name argument expected"); usage(stderr, 1); case 1: error(0, "metadata device argument expected"); usage(stderr, 1); case 2: error(0, "data device argument expected"); usage(stderr, 1); case 3: break; default: error(0, "unknown argument: %s", argv[3]); usage(stderr, 1); } name = argv[0]; meta = argv[1]; data = argv[2]; orig = malloc(16 + strlen(data)); if (!orig) { error(ENOMEM, NULL); return -1; } sprintf(orig, "%s-orig", name); /* * stat data device */ fd = blkopen(data, 0, &data_major, &data_minor, §ors); if (fd == -1) goto out; close(fd); /* * open metadata device */ md = md_open(meta, 1); if (!md) goto out; sb = md_block(md, MD_CACHED, 0, SUPERBLOCK_CSUM_XOR); if (!sb || era_sb_check(sb)) { md_close(md); goto out; } chunk = (int)le32toh(sb->data_block_size); nr_blocks = le32toh(sb->nr_blocks); meta_major = md->major; meta_minor = md->minor; /* * create empty era target */ snprintf(uuid, sizeof(uuid), "%s%u-%u", UUID_PREFIX, meta_major, meta_minor); if (era_dm_create_empty(name, uuid, NULL)) { md_close(md); goto out; } /* * rebuild spacemap */ if (era_spacemap_rebuild(md)) { (void)era_dm_remove(name); md_close(md); goto out; } md_close(md); /* * check nr_blocks */ chunks = (unsigned)((sectors + chunk - 1) / chunk); if (!force && chunks != (unsigned)nr_blocks) { (void)era_dm_remove(name); error(0, "can't open era device: data device resized\n" " %u chunks in superblock\n" " %u chunks in %s\n\n" "use \"--force\" option if you really resized data\n" "device and want to adjust era metadata device\n" "accordingly\n", (unsigned)nr_blocks, chunks, data); goto out; } /* * create orig target */ snprintf(uuid, sizeof(uuid), "%s%u-%u-orig", UUID_PREFIX, meta_major, meta_minor); snprintf(table, sizeof(table), "%u:%u 0", data_major, data_minor); if (era_dm_create(orig, uuid, 0, sectors, TARGET_LINEAR, table, &orig_info) == -1) { (void)era_dm_remove(name); goto out; } orig_major = (unsigned)orig_info.major; orig_minor = (unsigned)orig_info.minor; /* * load and resume era target */ snprintf(table, sizeof(table), "%u:%u %u:%u %d", meta_major, meta_minor, orig_major, orig_minor, chunk); if (era_dm_load(name, 0, sectors, TARGET_ERA, table, NULL)) { (void)era_dm_remove(orig); (void)era_dm_remove(name); goto out; } if (era_dm_resume(name)) { (void)era_dm_remove(orig); (void)era_dm_remove(name); goto out; } free(orig); return 0; out: free(orig); return -1; }