📄 util-linux-2.12r.diff
字号:
+ memcpy(n, p, y);+ memset(p, 0, y);+ free(p);+ }+ p = n;+ }+ if(rd_wr_retry(fd, p + y, 1, 0) != 1) break;+ if((p[y] == '\n') || !p[y]) break;+ y++;+ } while(1);+ if(p) p[y] = 0;+ return p;+}++static unsigned long long mystrtoull(char *s, int acceptAT)+{+ unsigned long long v = 0;+ int negative = 0;++ while ((*s == ' ') || (*s == '\t'))+ s++;+ if (acceptAT && (*s == '@')) {+ s++;+ negative = 1;+ }+ if (*s == '0') {+ s++;+ if ((*s == 'x') || (*s == 'X')) {+ s++;+ sscanf(s, "%llx", &v);+ } else {+ sscanf(s, "%llo", &v);+ }+ } else {+ sscanf(s, "%llu", &v);+ }+ return negative ? -v : v;+}++static void warnAboutBadKeyData(int x)+{+ if((x > 1) && (x != 64) && (x != 65)) {+ fprintf(stderr, _("Warning: Unknown key data format - using it anyway\n"));+ }+}++static char *do_GPG_pipe(char *pass)+{+ int x, pfdi[2], pfdo[2];+ char str[10], *a[16], *e[2], *h;+ pid_t gpid;+ struct passwd *p;+ void *oldSigPipeHandler;++ if((getuid() == 0) && gpgHomeDir && gpgHomeDir[0]) {+ h = gpgHomeDir;+ } else {+ if(!(p = getpwuid(getuid()))) {+ fprintf(stderr, _("Error: Unable to detect home directory for uid %d\n"), (int)getuid());+ return NULL;+ }+ h = p->pw_dir;+ }+ if(!(e[0] = malloc(strlen(h) + 6))) {+ nomem1:+ fprintf(stderr, _("Error: Unable to allocate memory\n"));+ return NULL;+ }+ sprintf(e[0], "HOME=%s", h);+ e[1] = 0;++ if(pipe(&pfdi[0])) {+ nomem2:+ free(e[0]);+ goto nomem1;+ }+ if(pipe(&pfdo[0])) {+ close(pfdi[0]);+ close(pfdi[1]);+ goto nomem2;+ }++ /*+ * When this code is run as part of losetup, normal read permissions+ * affect the open() below because losetup is not setuid-root.+ *+ * When this code is run as part of mount, only root can set+ * 'gpgKeyFile' and as such, only root can decide what file is opened+ * below. However, since mount is usually setuid-root all non-root+ * users can also open() the file too, but that file's contents are+ * only piped to gpg. This readable-for-all is intended behaviour,+ * and is very useful in situations where non-root users mount loop+ * devices with their own gpg private key, and yet don't have access+ * to the actual key used to encrypt loop device.+ */+ if((x = open(gpgKeyFile, O_RDONLY)) == -1) {+ fprintf(stderr, _("Error: unable to open %s for reading\n"), gpgKeyFile);+ nomem3:+ free(e[0]);+ close(pfdo[0]);+ close(pfdo[1]);+ close(pfdi[0]);+ close(pfdi[1]);+ return NULL;+ }++ /*+ * If someone puts a gpg key file at beginning of device and+ * puts the real file system at some offset into the device,+ * this code extracts that gpg key file into a temp file so gpg+ * won't end up reading whole device when decrypting the key file.+ *+ * Example of encrypted cdrom mount with 8192 bytes reserved for gpg key file:+ * mount -t iso9660 /dev/cdrom /cdrom -o loop=/dev/loop0,encryption=AES128,gpgkey=/dev/cdrom,offset=8192+ * ^^^^^^^^^^ ^^^^^^^^^^ ^^^^+ */+ if(loopOffsetBytes && !strcmp(loopFileName, gpgKeyFile)) {+ FILE *f;+ char b[1024];+ long long cnt;+ int cnt2, cnt3;++ cnt = mystrtoull(loopOffsetBytes, 1);+ if(cnt < 0) cnt = -cnt;+ if(cnt > (1024 * 1024)) cnt = 1024 * 1024; /* sanity check */+ f = tmpfile();+ if(!f) {+ fprintf(stderr, _("Error: unable to create temp file\n"));+ close(x);+ goto nomem3;+ }+ while(cnt > 0) {+ cnt2 = sizeof(b);+ if(cnt < cnt2) cnt2 = cnt;+ cnt3 = rd_wr_retry(x, b, cnt2, 0);+ if(cnt3 && (fwrite(b, cnt3, 1, f) != 1)) {+ tmpWrErr:+ fprintf(stderr, _("Error: unable to write to temp file\n"));+ fclose(f);+ close(x);+ goto nomem3;+ }+ if(cnt2 != cnt3) break;+ cnt -= cnt3;+ }+ if(fflush(f)) goto tmpWrErr;+ close(x);+ x = dup(fileno(f));+ fclose(f);+ lseek(x, 0L, SEEK_SET);+ }++ sprintf(str, "%d", pfdi[0]);+ if(!(gpid = fork())) {+ dup2(x, 0);+ dup2(pfdo[1], 1);+ close(x);+ close(pfdi[1]);+ close(pfdo[0]);+ close(pfdo[1]);+ if((x = open("/dev/null", O_WRONLY)) >= 0) {+ dup2(x, 2);+ close(x);+ }+ x = 0;+ a[x++] = "gpg";+ if(gpgHomeDir && gpgHomeDir[0]) {+ a[x++] = "--homedir";+ a[x++] = gpgHomeDir;+ }+ a[x++] = "--no-options";+ a[x++] = "--quiet";+ a[x++] = "--batch";+ a[x++] = "--no-tty";+ a[x++] = "--passphrase-fd";+ a[x++] = str;+ a[x++] = "--decrypt";+ a[x] = 0;+ if(setgid(getgid())) exit(1);+ if(setuid(getuid())) exit(1);+ for(x = 3; x < 1024; x++) {+ if(x == pfdi[0]) continue;+ close(x);+ }+ execve("/bin/gpg", &a[0], &e[0]);+ execve("/usr/bin/gpg", &a[0], &e[0]);+ execve("/usr/local/bin/gpg", &a[0], &e[0]);+ exit(1);+ }+ free(e[0]);+ close(x);+ close(pfdi[0]);+ close(pfdo[1]);+ if(gpid == -1) {+ close(pfdi[1]);+ close(pfdo[0]);+ goto nomem1;+ }++ x = strlen(pass);++ /* ignore possible SIGPIPE signal while writing to gpg */+ oldSigPipeHandler = signal(SIGPIPE, SIG_IGN);+ rd_wr_retry(pfdi[1], pass, x, 1);+ rd_wr_retry(pfdi[1], "\n", 1, 1);+ if(oldSigPipeHandler != SIG_ERR) signal(SIGPIPE, oldSigPipeHandler);++ close(pfdi[1]);+ memset(pass, 0, x);+ x = 0;+ while(x < 66) {+ multiKeyPass[x] = get_FD_pass(pfdo[0]);+ if(!multiKeyPass[x]) {+ /* mem alloc failed - abort */+ multiKeyPass[0] = 0; break;+ }+ if(strlen(multiKeyPass[x]) < LOOP_PASSWORD_MIN_LENGTH) break;+ x++;+ }+ warnAboutBadKeyData(x);+ if(x >= 65)+ multiKeyMode = 65;+ if(x == 64)+ multiKeyMode = 64;+ close(pfdo[0]);+ waitpid(gpid, &x, 0);+ if(!multiKeyPass[0]) goto nomem1;+ return multiKeyPass[0];+}++static char *sGetPass(int minLen, int warnLen)+{+ char *p, *s, *seed;+ int i, ask2, close_i_fd = 0;++ if(!passFDnumber) {+ if(clearTextKeyFile) {+ if((i = open(clearTextKeyFile, O_RDONLY)) == -1) {+ fprintf(stderr, _("Error: unable to open %s for reading\n"), clearTextKeyFile);+ return NULL;+ }+ close_i_fd = 1;+ goto contReadFrom_i;+ }+ p = getpass(_("Password: "));+ ask2 = passAskTwice ? 1 : 0;+ } else {+ i = atoi(passFDnumber);+ contReadFrom_i:+ if(gpgKeyFile && gpgKeyFile[0]) {+ p = get_FD_pass(i);+ if(close_i_fd) close(i);+ } else {+ int x = 0;+ while(x < 66) {+ multiKeyPass[x] = get_FD_pass(i);+ if(!multiKeyPass[x]) goto nomem;+ if(strlen(multiKeyPass[x]) < LOOP_PASSWORD_MIN_LENGTH) break;+ x++;+ }+ if(close_i_fd) close(i);+ warnAboutBadKeyData(x);+ if(x >= 65) {+ multiKeyMode = 65;+ return multiKeyPass[0];+ }+ if(x == 64) {+ multiKeyMode = 64;+ return multiKeyPass[0];+ }+ p = multiKeyPass[0];+ }+ ask2 = 0;+ }+ if(!p) goto nomem;+ if(gpgKeyFile && gpgKeyFile[0]) {+ if(ask2) {+ i = strlen(p);+ s = malloc(i + 1);+ if(!s) goto nomem;+ strcpy(s, p);+ p = getpass(_("Retype password: "));+ if(!p) goto nomem;+ if(strcmp(s, p)) goto compareErr;+ memset(s, 0, i);+ free(s);+ ask2 = 0;+ }+ p = do_GPG_pipe(p);+ if(!p) return(NULL);+ if(!p[0]) {+ fprintf(stderr, _("Error: gpg key file decryption failed\n"));+ return(NULL);+ }+ if(multiKeyMode) return(p);+ }+ i = strlen(p);+ if(i < minLen) {+ fprintf(stderr, _("Error: Password must be at least %d characters.\n"), minLen);+ return(NULL);+ }+ seed = passSeedString;+ if(!seed) seed = "";+ s = malloc(i + strlen(seed) + 1);+ if(!s) {+ nomem:+ fprintf(stderr, _("Error: Unable to allocate memory\n"));+ return(NULL); }+ strcpy(s, p);+ memset(p, 0, i);+ if(ask2) {+ p = getpass(_("Retype password: "));+ if(!p) goto nomem;+ if(strcmp(s, p)) {+ compareErr:+ fprintf(stderr, _("Error: Passwords are not identical\n"));+ return(NULL);+ }+ memset(p, 0, i);+ }+ if(i < warnLen) {+ fprintf(stderr, _("WARNING - Please use longer password (%d or more characters)\n"), LOOP_PASSWORD_MIN_LENGTH);+ }+ strcat(s, seed);+ return(s);+} - if (pass == NULL)- return "";+/* this is for compatibility with historic loop-AES version */+static void unhashed1_key_setup(unsigned char *keyStr, int ile, unsigned char *keyBuf, int bufSize)+{+ register int x, y, z, cnt = ile;+ unsigned char *kp; - pass[i] = 0;- return pass;+ memset(keyBuf, 0, bufSize);+ kp = keyStr;+ for(x = 0; x < (bufSize * 8); x += 6) {+ y = *kp++;+ if(--cnt <= 0) {+ kp = keyStr;+ cnt = ile;+ }+ if((y >= '0') && (y <= '9')) y -= '0';+ else if((y >= 'A') && (y <= 'Z')) y -= ('A' - 10);+ else if((y >= 'a') && (y <= 'z')) y -= ('a' - 36);+ else if((y == '.') || (y == '/')) y += (62 - '.');+ else y &= 63;+ z = x >> 3;+ if(z < bufSize) {+ keyBuf[z] |= y << (x & 7);+ }+ z++;+ if(z < bufSize) {+ keyBuf[z] |= y >> (8 - (x & 7));+ }+ } } -static int-digits_only(const char *s) {- while (*s)- if (!isdigit(*s++))- return 0;- return 1;+/* this is for compatibility with mainline mount */+static void unhashed2_key_setup(unsigned char *keyStr, int ile, unsigned char *keyBuf, int bufSize)+{+ memset(keyBuf, 0, bufSize);+ strncpy((char *)keyBuf, (char *)keyStr, bufSize - 1);+ keyBuf[bufSize - 1] = 0;+}++static void rmd160HashTwiceWithA(unsigned char *ib, int ile, unsigned char *ob, int ole)+{+ char tmpBuf[20 + 20];+ char pwdCopy[130];++ if(ole < 1) return;+ memset(ob, 0, ole);+ if(ole > 40) ole = 40;+ rmd160_hash_buffer(&tmpBuf[0], (char *)ib, ile);+ pwdCopy[0] = 'A';+ if(ile > sizeof(pwdCopy) - 1) ile = sizeof(pwdCopy) - 1;+ memcpy(pwdCopy + 1, ib, ile);+ rmd160_hash_buffer(&tmpBuf[20], pwdCopy, ile + 1);+ memcpy(ob, tmpBuf, ole);+ memset(tmpBuf, 0, sizeof(tmpBuf));+ memset(pwdCopy, 0, sizeof(pwdCopy));+}++extern long long llseek(int, long long, int);++static long long xx_lseek(int fd, long long offset, int whence)+{+ if(sizeof(off_t) >= 8) {+ return lseek(fd, offset, whence);+ } else {+ return llseek(fd, offset, whence);+ }+}++static int loop_create_random_keys(char *partition, long long offset, long long sizelimit, int loopro, unsigned char *k)+{+ int x, y, fd;+ sha512_context s;+ unsigned char b[4096];++ if(loopro) {+ fprintf(stderr, _("Error: read-only device %s\n"), partition);+ return 1;+ }++ /*+ * Compute SHA-512 over first 40 KB of old fs data. SHA-512 hash+ * output is then used as entropy for new fs encryption key.+ */+ if((fd = open(partition, O_RDWR)) == -1) {+ seekFailed:+ fprintf(stderr, _("Error: unable to open/seek device %s\n"), partition);+ return 1;+ }+ if(offset < 0) offset = -offset;+ if(xx_lseek(fd, offset, SEEK_SET) == -1) {+ close(fd);+ goto seekFailed;+ }+ sha512_init(&s);+ for(x = 1; x <= 10; x++) {+ if((sizelimit > 0) && ((sizeof(b) * x) > sizelimit)) break;+ if(rd_wr_retry(fd, &b[0], sizeof(b), 0) != sizeof(b)) break;+ sha512_write(&s, &b[0], sizeof(b));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -