📄 armour.c
字号:
{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }};keymanager_t *get_keymanager(const struct keyinfo *keyinfo) /* search for keymanager that supports given key */{ keymanager_t *km; int is_raw; if (keyinfo == NULL) return NULL; is_raw = (strcmp(keyinfo->cipheralg, "none") == 0); for (km=keymgrs; km->ident!=NULL; ++km) { if (is_raw && strcmp(km->ident, "raw") != 0) continue; if (km->is_compat(keyinfo)) { return init_keymanager(km); } } return NULL;}keymanager_t *init_keymanager(keymanager_t *km){ if (km != NULL) { if (!km->initialized) { km->init_algs(); /* FIXME - check return status */ km->initialized = 1; } } return km;}int free_keymanagers(){ keymanager_t *km; for (km=keymgrs; km->ident!=NULL; ++km) { if (km->initialized) { km->free_algs(); km->initialized = 0; } } return 0;}int km_get_passwd(const char *ident, char **passwd, int new, int verify) /* read password from terminal, possibly asking for confirmation */{ enum { BUFFSZ=2048 }; char *tmppass,buff[BUFFSZ]; size_t plen; int eflag=ERR_NOERROR; snprintf(buff, sizeof(buff), (new ? _("enter new password for target \"%s\": ") : _("enter password for target \"%s\": ")), ident); tmppass = getpass(buff); plen = strlen(tmppass); *passwd = (char*)sec_realloc((void*)*passwd, (plen + 1)); strcpy(*passwd, tmppass); mem_cleanse((unsigned char*)tmppass, plen + 1); if (verify) { snprintf(buff, sizeof(buff), _("confirm password: ")); tmppass = getpass(buff); plen = strlen(tmppass); if (strcmp(*passwd, tmppass) != 0) { fprintf(stderr, _("password mismatch\n")); sec_free(*passwd); *passwd = NULL; eflag = ERR_BADPASSWD; } mem_cleanse((unsigned char*)tmppass, plen); } return eflag;}int get_key(const char *ident, const keyinfo_t *keyinfo, unsigned char **key, int *keylen){ keymanager_t *km; FILE *fp=NULL; int eflag=ERR_NOERROR; if (keyinfo == NULL || keyinfo->filename == NULL) { fprintf(stderr, _("missing key-file for target \"%s\"\n"), ident); eflag = ERR_BADFILE; goto bail_out; } if ((km = get_keymanager(keyinfo)) != NULL) { if ((fp=fopen(keyinfo->filename, "rb")) == NULL) { fprintf(stderr, _("failed to open keyfile \"%s\" for target \"%s\"\n"), keyinfo->filename, ident); eflag = ERR_BADFILE; goto bail_out; } eflag = km->get_key(ident, keyinfo, key, keylen, fp); } else { fprintf(stderr, _("unrecognized key format for target \"%s\"\n"), ident); eflag = ERR_BADKEYFORMAT; } bail_out: if (fp != NULL) fclose(fp); return eflag;}int put_key(const char *ident, const keyinfo_t *keyinfo, const unsigned char *key, const int keylen, FILE *fp_key){ keymanager_t *km; if (fp_key == NULL) { fprintf(stderr, _("missing output stream for target \"%s\"\n"), ident); return ERR_BADFILE; } if ((km = get_keymanager(keyinfo)) != NULL) { return km->put_key(ident, keyinfo, key, keylen, fp_key); } return ERR_BADKEYFORMAT;}int is_keysafe(const keyinfo_t *keyinfo) /* check whether key is stored in encrypted form */{ return (keyinfo != NULL && keyinfo->cipheralg != NULL && strcmp(keyinfo->cipheralg, "none") != 0);}int get_randkey(unsigned char *buff, unsigned len) /* generate random string of bytes */{ struct rnddev { const char *name; unsigned devmaj, devmin; FILE *fp; }; struct rnddev devs[] = { { "/dev/hwrng", MISC_MAJOR, 183, NULL }, { "/dev/random", MEM_MAJOR, 8, NULL }, { "/dev/urandom", MEM_MAJOR, 9, NULL }, { NULL, 0, 0, NULL } }; keymanager_t *kmgr=NULL; void *mdcontext=NULL; unsigned char *mdval,*devbuff=NULL; unsigned pos,sz,mdlen; int i,cnt,eflag=ERR_NOERROR; struct stat sbuff; pid_t pid; struct tms tbuff; clock_t clk; static unsigned seed=17; /* assume first entry in key-manager list is decent quality: */ kmgr = init_keymanager(keymgrs); /* try to find good-quality random-number devices: */ for (i=0,cnt=0; devs[i].name!=NULL; ++i) { if (stat(devs[i].name, &sbuff) != 0) continue; if ((unsigned)major(sbuff.st_rdev) != devs[i].devmaj || (unsigned)minor(sbuff.st_rdev) != devs[i].devmin) continue; if ((devs[i].fp = fopen(devs[i].name,"rb")) != NULL) ++cnt; } if (cnt == 0) { fprintf(stderr, _("no random-number devices found")); eflag = WRN_LOWENTROPY; } devbuff = (unsigned char*)sec_realloc(NULL, (size_t)len); pid = getpid(); /* combine multiple sources of entropy (should still be effective if subset aren't viable): */ pos = 0; while (pos < len) { mdcontext = kmgr->md_prepare(); /* fold-in entropy from random-number devices: */ for (i=0; devs[i].name!=NULL; ++i) { if (devs[i].fp == NULL) continue; (void)fread((void*)devbuff, 1, (size_t)len, devs[i].fp); kmgr->md_block(mdcontext, devbuff, len); } /* fold-in some (weak) sources of entropy: */ kmgr->md_block(mdcontext, (unsigned char*)&pid, sizeof(pid)); clk = times(&tbuff); kmgr->md_block(mdcontext, (unsigned char*)&clk, sizeof(clk)); kmgr->md_block(mdcontext, (unsigned char*)&seed, sizeof(seed)); kmgr->md_block(mdcontext, (unsigned char*)&tbuff, sizeof(tbuff)); kmgr->md_final(mdcontext, &mdval, &mdlen); sz = ((pos + mdlen) > len ? (len - pos) : mdlen); memcpy((void*)(buff + pos),(const void*)mdval, (size_t)sz); pos += sz; seed = seed * 20 + 1; kmgr->md_release(mdcontext); } sec_free((void*)devbuff); for (i=0; devs[i].name!=NULL; ++i) { if (devs[i].fp != NULL) fclose(devs[i].fp); } return eflag;}#ifdef TESTINGint km_test_keyrw() /* test key read-writing (creation/extraction) */{ enum { MAXKEY=256 }; keymanager_t *km; keyinfo_t keyinfo; int i,keylen,keylen1; char str[256]; unsigned char key0[MAXKEY],*key1=NULL; FILE *fp; CM_TEST_START("key read-write"); for (km=keymgrs; km->ident!=NULL; ++km) { keyinfo.format = NULL; keyinfo.filename = "NOWHERE"; keyinfo.digestalg = NULL; keyinfo.cipheralg = NULL; keyinfo.maxlen = -1; km->mk_default(&keyinfo); km->init_algs(); for (keylen=1; keylen<=MAXKEY; keylen<<=2) { sprintf(str, "key read-write, %s, keylen=%d", km->ident, keylen); CM_TEST_IDENT(str); /* generate (low-entropy) key: */ for (i=0; i<keylen; ++i) { key0[i] = (i * 0x9d) ^ ((keylen * (unsigned long)km) % 253); } /* write key to file: */ fp = tmpfile(); if (fp == NULL) CM_TEST_ABORT(); i = km->put_key("TEST-OUT", &keyinfo, key0, keylen, fp); CM_ASSERT_EQUAL(ERR_NOERROR, i); key1 = NULL; keylen1 = -keylen; /* try reading key back from file: */ rewind(fp); i = km->get_key("TEST-IN", &keyinfo, &key1, &keylen1, fp); CM_ASSERT_EQUAL(ERR_NOERROR, i); CM_ASSERT_EQUAL(keylen, keylen1); CM_ASSERT_DIFFERENT(key0, key1); CM_ASSERT_DIFFERENT(NULL, key1); for (i=0; i<keylen; ++i) { CM_ASSERT_EQUAL(key0[i], key1[i]); } fclose(fp); sec_free(key1); } km->free_algs(); free((void*)keyinfo.cipheralg); free((void*)keyinfo.digestalg); } CM_TEST_OK();}#endif /* TESTING *//* * ==== miscellaneous routines ==== */void *sec_realloc(void *ptr, size_t size) /* slightly more secure version of realloc() */{ unsigned char *addr=NULL; addr = (unsigned char*)malloc(size + sizeof(size_t)); if (addr == NULL) { fprintf(stderr, _("unable to allocated memory\n")); abort(); return NULL; } /* prepend usable memory chunk with record of size of chunk: */ *((size_t*)addr) = size; addr += sizeof(size_t); if (ptr != NULL) { unsigned char *old; unsigned i,oldsz; /* copy (usable) part of old memory block into new: */ old = (unsigned char*)ptr; oldsz = *((size_t*)(old - sizeof(size_t))); if (oldsz > size) oldsz = size; for (i=0; i<oldsz; ++i) addr[i] = old[i]; /* dispose of old memory block: */ sec_free(ptr); } return (void*)addr;}void mem_cleanse(unsigned char *addr, size_t sz) /* overwrite memory with (weak) pseudo-random numbers */{ size_t i; static unsigned long salt=0x917c; salt ^= (unsigned long)addr; for (i=0; i<sz; ++i) { addr[i] = (i % 21) ^ (salt % 221); salt += 4; }}void sec_free(void *ptr) /* slightly more secure version of free() */{ unsigned char *addr; size_t sz; if (ptr == NULL) return; addr = (unsigned char*)ptr; sz = *((size_t*)(addr - sizeof(size_t))); mem_cleanse(addr, sz); free((void*)(addr - sizeof(size_t)));}int mk_key_string(const unsigned char *key, const int keylen, char *buff) /* create text version of crypto key */{ int i; for (i=0; i<keylen; ++i) { sprintf(buff+2*i, "%02x", key[i]); } return (2 * keylen);}int sycheck_cmtab(const char *cmtab) /* check that permissions on ${sysconfdir}/cryptmount/cmtab are sensible */{ struct stat sfile,sdir; char *dirname=NULL; int pos,eflag=ERR_NOERROR; /* extract directory name from cmtab filename: */ pos = strlen(cmtab); dirname = (char*)malloc((size_t)(pos + 1)); for ( ; pos>0 && cmtab[pos-1] != '/'; --pos) dirname[pos] = '\0'; while (--pos >= 0) dirname[pos] = cmtab[pos]; if (stat(cmtab,&sfile) != 0 || stat(dirname,&sdir) != 0) { fprintf(stderr, "cannot open \"%s\" or \"%s\"\n", cmtab, dirname); eflag = ERR_INSECURE; goto bail_out; } /* check file/directory ownerships: */ if (sfile.st_uid != (uid_t)0 || sdir.st_uid != (uid_t)0) { fprintf(stderr, "\"%s\" and \"%s\" must be owned by root\n", cmtab, dirname); eflag = ERR_INSECURE; goto bail_out; } /* check that file isn't globally writable: */ if (!S_ISREG(sfile.st_mode) || (sfile.st_mode & S_IWOTH) != 0) { fprintf(stderr, "lax permissions on \"%s\"\n", cmtab); eflag = ERR_INSECURE; goto bail_out; } /* check that directory isn't globally writable: */ if (!S_ISDIR(sdir.st_mode) || (sdir.st_mode & S_IWOTH) != 0) { fprintf(stderr, "lax permissions on \"%s\"\n", dirname); eflag = ERR_INSECURE; goto bail_out; } bail_out: if (dirname != NULL) free((void*)dirname); return eflag;}static int sy_path(const char *path) /* check whether pathname is considered secure */{ if (path == NULL) return ERR_NOERROR; if (path[0] == '/') return ERR_NOERROR; return ERR_INSECURE;}int sycheck_target(const cment_t *cment) /* check that paths within target-specification are sensible */{ int eflag=ERR_NOERROR; if (cment == NULL) return 0; eflag |= sy_path(cment->dev); eflag |= sy_path(cment->dir); eflag |= sy_path(cment->key.filename); if (eflag != ERR_NOERROR) { fprintf(stderr, "specification for target \"%s\" contains non-absolute pathname\n", cment->ident); } return eflag;}/* * ==== mutex-locking on configuration directory ==== */int cm_mutex_lock() /* try to acquire lock on configuration directory (via symlink marker) */{ char *fname=NULL,ident[64]; int tries=3,eflag=1; (void)cm_path(&fname, "_lock_"); sprintf(ident, "%u-%u", (unsigned)getpid(), (unsigned)getuid()); while (tries-->0) { if (symlink(ident, fname) == 0) { /* lock acquired */ eflag = 0; break; } else { if (errno == EEXIST) sleep(1); /* try again later */ else break; /* failed to make link for more peculiar reason */ } } if (eflag != 0) { fprintf(stderr, "failed to create lock-file \"%s\"\n", fname); } free((void*)fname); return eflag;}int cm_mutex_unlock() /* release lock on configuration directory */{ char *fname=NULL; struct stat sbuff; int eflag=0; (void)cm_path(&fname, "_lock_"); if (lstat(fname, &sbuff) != 0 || !S_ISLNK(sbuff.st_mode) || unlink(fname) != 0) { fprintf(stderr, "failed to remove lock-file \"%s\"\n", fname); eflag = 1; } free((void*)fname); return eflag;}/* * (C)Copyright 2005-2006, RW Penney */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -