📄 cryptmount.c
字号:
/* * cryptmount - a utility for user-level mounting of encrypted filesystems * $Revision: 117 $, $Date: 2006-07-30 10:20:45 +0100 (Sun, 30 Jul 2006) $ * Copyright 2005-2006 RW Penney *//* This file is part of cryptmount cryptmount 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. As a special exemption, permission is granted to link cryptmount with the OpenSSL project's "OpenSSL" library and distribute the linked code without invoking clause 2(b) of the GNU GPL version 2. cryptmount 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 cryptmount; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */#include <config.h>#include <ctype.h>#include <fcntl.h>#include <getopt.h>#include <inttypes.h>#include <pwd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <sys/mount.h>#include <sys/stat.h>#include <sys/types.h>#ifdef HAVE_SYSLOG# include <syslog.h>#endif#include "armour.h"#include "cryptmount.h"#include "delegates.h"#include "dmutils.h"#include "fsutils.h"#include "looputils.h"#include "tables.h"#ifdef TESTING# include "cmtesting.h"#endifstruct targelt_t{ const cment_t *entry; struct targelt_t *nx;};enum mode_t{ M_DEFAULT, M_HELP, M_PREPARE, M_RELEASE, M_MOUNT, M_UNMOUNT, M_SWAPON, M_SWAPOFF, M_LIST, M_PASSWORD, M_KEYGEN, M_VERSION};int execute_list(enum mode_t mode, const char *params, const struct targelt_t *eltlist);int do_list(const cment_t *cment);int do_devsetup(const cment_t *cment, char **mntdev);int do_devshutdown(const cment_t *cment);int do_mount(const cment_t *cment);int do_unmount(const cment_t *cment);int do_swapon(const cment_t *cment);int do_swapoff(const cment_t *cment);int do_passwd(const cment_t *cment);int do_keygen(const cment_t *cment, const char *params);static const char *USAGE_STRING=N_("\usage: cryptmount [OPTION [target ...]]\n\\n\ available options are as follows:\n\\n\ -h | --help\n\ -a | --all\n\ -c | --change-password <target>\n\ -l | --list\n\ -m | --mount <target>\n\ -u | --unmount <target>\n\ --generate-key <key-size> <target>\n\ --prepare <target>\n\ --release <target>\n\ --swapon <target>\n\ --swapoff <target>\n\ --version\n\\n\ please report bugs to cryptmount@rwpenney.org.uk\n\");#ifdef TESTING/* allow config-file & password to be specified via command-line, to enable automatic testing: */const char *argconfigdir=NULL;const char *argpassword[]={ NULL, NULL };#endifint do_list(const cment_t *cment) /* print list of available filing-system targets */{ printf(_("%-16s [to mount on \"%s\" as \"%s\"]\n"), cment->ident, cment->dir, cment->fstype); return ERR_NOERROR;}int do_devsetup(const cment_t *cment, char **mntdev) /* setup all devices needed to access encrypted target */{ enum { BUFFMIN=1024 }; unsigned char *key=NULL; int i,fd=-1,killloop=0,keylen=0,eflag=ERR_NOERROR; long devlen=0,fslen=0; struct stat sbuff; char *dmparams=NULL,*tgtdev=NULL,*loopdev=NULL; /* get crypto-key for filing system: */ eflag = get_key(cment->ident, &cment->key, &key, &keylen); if (eflag != ERR_NOERROR) { fprintf(stderr, _("failed to extract cipher key\n")); goto bail_out; } if (cment->dev == NULL || stat(cment->dev, &sbuff) != 0) { fprintf(stderr, _("cannot stat device \"%s\" for target \"%s\"\n"), (cment->dev != NULL ? cment->dev : "(NULL)"), cment->ident); eflag = ERR_BADDEVICE; goto bail_out; } /* check whether using raw device or loopback to file: */ if (S_ISBLK(sbuff.st_mode)) { tgtdev = cment->dev; } else if (S_ISREG(sbuff.st_mode)) { if (cment->loopdev != NULL && strcmp(cment->loopdev, "auto") != 0) { loopdev = (char*)malloc((size_t)(strlen(cment->loopdev) + 1)); strcpy(loopdev, cment->loopdev); } else { loopdev = (char*)malloc((size_t)BUFFMIN); if (loop_findfree(loopdev, BUFFMIN) != 0) { fprintf(stderr, _("no available loopback devices\n")); eflag = ERR_BADDEVICE; goto bail_out; } } eflag = loop_setup(loopdev, cment->dev, (is_readonlyfs(cment->dev) ? O_RDONLY : O_RDWR)); tgtdev = loopdev; } else { fprintf(stderr, _("bad device type (%x) for \"%s\" (need block/file)\n"), (unsigned)sbuff.st_mode, cment->dev); tgtdev = NULL; eflag = ERR_BADDEVICE; goto bail_out; } /* get size in blocks of target device: */ fd = open(tgtdev, O_RDONLY); if (ioctl(fd, BLKGETSIZE, &devlen) != 0) { fprintf(stderr, _("failed to get size of \"%s\"\n"), tgtdev); eflag = ERR_BADIOCTL; goto bail_out; } if (cment->length < 0 || (cment->start + cment->length) > devlen) { fslen = devlen - cment->start; } else { fslen = cment->length; } if (cment->start < 0 || fslen <= 0) { fprintf(stderr, _("bad device-mapper start/length (%ld,%ld)\n"), cment->start, cment->length); eflag = ERR_BADDEVICE; goto bail_out; } /* setup device-mapper crypt table (CIPHER KEY IV_OFFSET DEV START): */ dmparams = sec_realloc(dmparams, (size_t)(2 * keylen + BUFFMIN)); i = sprintf(dmparams, "%s ", (cment->cipher != NULL ? cment->cipher : DFLT_CIPHER)); mk_key_string(key, keylen, dmparams + i); sprintf(dmparams + strlen(dmparams), " %ld %s %ld", cment->ivoffset, tgtdev, cment->start); /* setup device-mapper target: */ eflag = devmap_create(cment->ident, (uint64_t)0, (uint64_t)fslen, "crypt", dmparams); if (eflag != ERR_NOERROR) { fprintf(stderr, _("device-mapper target-creation failed for \"%s\"\n"), cment->ident); killloop = 1; goto bail_out; } if (mntdev != NULL) { devmap_path(mntdev, cment->ident); } bail_out: if (fd != -1) close(fd); if (loopdev != NULL) { if (killloop) loop_destroy(loopdev); /* mounting failed? */ free((void*)loopdev); } sec_free(dmparams); sec_free(key); return eflag;} /* do_devsetup() */int do_devshutdown(const cment_t *cment) /* remove all devices attached to encrypted target */{ struct stat sbuff; unsigned i,devcnt=0; int eflag=ERR_NOERROR; dev_t *devids=NULL; char buff[256]; /* check if filing system has been configured at all: */ if (!is_configured(cment->ident, NULL)) { fprintf(stderr, _("target \"%s\" does not appear to be configured\n"), cment->ident); eflag = WRN_UNCONFIG; goto bail_out; } /* find any underlying (e.g. loopback) devices for device-mapper target: */ (void)devmap_dependencies(cment->ident, &devcnt, &devids);#ifdef DEBUG fprintf(stderr, "shutting down %s [%u dependencies]\n", cment->ident, devcnt);#endif if (stat(cment->dev, &sbuff) != 0) { fprintf(stderr, _("cannot stat \"%s\"\n"), cment->dev); eflag = ERR_BADDEVICE; goto bail_out; } /* remove demice-mapper target: */ eflag = devmap_remove(cment->ident); if (eflag != ERR_NOERROR) { fprintf(stderr, _("failed to remove device-mapper target \"%s\"\n"), cment->ident); goto bail_out; } /* tidy-up any associated loopback devices: */ if (S_ISREG(sbuff.st_mode) && devids != NULL) { for (i=0; i<devcnt; ++i) { if (loop_ident(major(devids[i]),minor(devids[i]),buff,sizeof(buff)) || (loop_destroy(buff) != ERR_NOERROR)) { fprintf(stderr, _("failed to free device (%d,%d)\n"), major(devids[i]), minor(devids[i])); } } } bail_out: if (devids != NULL) free((void*)devids); return eflag;}int do_mount(const cment_t *cment){ int freedev=0,eflag=ERR_NOERROR; char *mntdev=NULL; tgtstat_t *tstat; if (is_mounted(cment)) { fprintf(stderr, _("target \"%s\" is already mounted\n"), cment->ident); eflag = ERR_BADMOUNT; goto bail_out; } eflag = do_devsetup(cment, &mntdev); if (eflag != ERR_NOERROR) goto bail_out;#if WITH_FSCK if ((cment->flags & FLG_FSCK) != 0) { if (fs_check(mntdev, cment) != ERR_NOERROR) { freedev = 1; eflag = ERR_BADMOUNT; goto bail_out; } }#endif if (fs_mount(mntdev, cment) != ERR_NOERROR) { freedev = 1; eflag = ERR_BADMOUNT; goto bail_out; } tstat = alloc_tgtstatus(cment); tstat->uid = (unsigned long)getuid(); put_tgtstatus(cment, tstat); free_tgtstatus(tstat); bail_out: if (freedev) { /* tidy-up debris if mount failed */ do_devshutdown(cment); } if (mntdev != NULL) free((void*)mntdev); return eflag;}int do_unmount(const cment_t *cment){ int eflag=ERR_NOERROR; struct passwd *pwent; char *mntdev=NULL; tgtstat_t *tstat; /* check if filing system has been configured at all: */ if (!is_mounted(cment) || (tstat = get_tgtstatus(cment)) == NULL) { fprintf(stderr, _("target \"%s\" does not appear to be mounted\n"), cment->ident); eflag = WRN_UNCONFIG; goto bail_out; } /* check if filing system has been mounted & locked by another user: */ if (getuid() != 0 && (uid_t)tstat->uid != getuid()) { pwent = getpwuid((uid_t)tstat->uid); if (pwent != NULL) { fprintf(stderr, _("only \"%s\" can unmount \"%s\"\n"), pwent->pw_name, cment->ident); } else { fprintf(stderr, _("only user-%lu can unmount \"%s\"\n"), tstat->uid, cment->ident); } eflag = ERR_BADPRIV; goto bail_out; } /* unmount filing system: */ if (fs_unmount(cment) != ERR_NOERROR) { eflag = ERR_BADMOUNT; goto bail_out; } put_tgtstatus(cment, NULL); /* remove supporting device-mapper target etc */ if (do_devshutdown(cment) != ERR_NOERROR) { eflag = ERR_BADDEVICE; } bail_out: if (mntdev != NULL) free((void*)mntdev); return eflag;}int do_swapon(const cment_t *cment){ int freedev=0,eflag=ERR_NOERROR; char *mntdev=NULL; tgtstat_t *tstat;#if WITH_CSWAP eflag = do_devsetup(cment, &mntdev); if (eflag != ERR_NOERROR) goto bail_out; if (fs_swapon(mntdev, cment) != ERR_NOERROR) { freedev = 1; eflag = ERR_BADSWAP; goto bail_out; } tstat = alloc_tgtstatus(cment); tstat->uid = (unsigned long)getuid(); put_tgtstatus(cment, tstat); free_tgtstatus(tstat);#else /* !WITH_CSWAP */ fprintf(stderr, _("crypto-swap is not supported by this installation of cryptmount\n")); eflag = ERR_BADSWAP;#endif bail_out: if (freedev) { /* tidy-up debris if swapon failed */ do_devshutdown(cment); } if (mntdev != NULL) free((void*)mntdev); return eflag;}int do_swapoff(const cment_t *cment){ int eflag=ERR_NOERROR; char *mntdev=NULL; tgtstat_t *tstat;#if WITH_CSWAP /* check if device has been configured at all: */ if ((tstat = get_tgtstatus(cment)) == NULL) { fprintf(stderr, _("target \"%s\" does not appear to be configured\n"), cment->ident); eflag = WRN_UNCONFIG; goto bail_out; } /* remove swap-partition: */ if (fs_swapoff(cment) != ERR_NOERROR) { eflag = ERR_BADSWAP; goto bail_out; } put_tgtstatus(cment, NULL); /* remove supporting device-mapper target etc */ if (do_devshutdown(cment) != ERR_NOERROR) { eflag = ERR_BADDEVICE; }#else /* !WITH_CSWAP */ fprintf(stderr, _("crypto-swap is not supported by this installation of cryptmount\n")); eflag = ERR_BADSWAP;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -