Репозитории ALT
Группа :: Система/Основа
Пакет: hashalot
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: hashalot-0.3-alt1.qa1.patch
Скачать
Скачать
ChangeLog | 2 +-
Makefile.am | 14 ++-
configure.ac | 19 +++-
getline.h | 39 +++++++
getpass.c | 182 +++++++++++++++++++++++++++++++++
getpass.h | 7 ++
hashalot.1 | 42 --------
hashalot.8 | 42 ++++++++
hashalot.c | 323 +++++++++++++++++++++++++++++++---------------------------
sha512.c | 14 +--
sha512.h | 10 +-
unlocked-io.h | 132 ++++++++++++++++++++++++
12 files changed, 614 insertions(+), 212 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index b3fd1f7..909db3c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -23,7 +23,7 @@
* forgot to erase the passphrase from memory when using a salt
* manpage created
-
+
2004-02-08 Ben Slusky <sluskyb@paranoiacs.org>
diff --git a/Makefile.am b/Makefile.am
index 4fcc6fd..973e063 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,9 +1,9 @@
sbin_PROGRAMS = hashalot
-man_MANS = hashalot.1
+man_MANS = hashalot.8
-hashalot_SOURCES = hashalot.c rmd160.c rmd160.h sha512.c sha512.h
+hashalot_SOURCES = hashalot.c getpass.c rmd160.c rmd160.h sha512.c sha512.h
install-exec-hook:
cd $(DESTDIR)$(sbindir) && \
@@ -12,9 +12,19 @@ install-exec-hook:
$(LN_S) -f hashalot$(EXEEXT) sha384$(EXEEXT) && \
$(LN_S) -f hashalot$(EXEEXT) sha512$(EXEEXT)
+install-data-hook:
+ cd $(DESTDIR)$(mandir)/man8 && \
+ $(LN_S) -f hashalot.8 rmd160.8 && \
+ $(LN_S) -f hashalot.8 sha256.8 && \
+ $(LN_S) -f hashalot.8 sha384.8 && \
+ $(LN_S) -f hashalot.8 sha512.8
+
uninstall-hook:
cd $(DESTDIR)$(sbindir) && \
rm -f rmd160 sha256 sha384 sha512
+ cd $(DESTDIR)$(mandir)/man8 && \
+ rm -f rmd160.8 sha256.8 sha384.8 sha512.8
TESTS = check.sh
+EXTRA_DIST = check.sh
diff --git a/configure.ac b/configure.ac
index d14db24..31996c2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,12 +1,25 @@
AC_INIT(hashalot.c)
-AM_INIT_AUTOMAKE(hashalot, 0.1.0)
+AM_INIT_AUTOMAKE(hashalot, 0.3.0)
+AC_CONFIG_HEADERS([config.h])
+AC_GNU_SOURCE
AC_PROG_INSTALL
AC_PROG_CC
AC_PROG_LN_S
AC_HEADER_STDC
-AC_CHECK_HEADERS(libgen.h stdio.h stdlib.h string.h unistd.h assert.h sys/types.h sys/mman.h endian.h , , [ AC_MSG_ERROR(required header not found)])
-AC_CHECK_FUNCS(getopt snprintf , , [ AC_MSG_ERROR(required function not found)])
+AC_CHECK_HEADERS(
+ [errno.h error.h stdbool.h stddef.h stdio.h stdio_ext.h \
+ stdlib.h string.h unistd.h sys/types.h sys/mman.h endian.h], ,
+ [AC_MSG_ERROR(required header not found)])
+AC_CHECK_FUNCS(
+ [asprintf error getline getopt snprintf tcgetattr], ,
+ [AC_MSG_ERROR(required function not found)])
+
+AC_CHECK_DECLS(
+ [clearerr_unlocked, feof_unlocked, ferror_unlocked,
+ fflush_unlocked, fgets_unlocked, fputc_unlocked, fputs_unlocked,
+ fread_unlocked, fwrite_unlocked, getc_unlocked,
+ getchar_unlocked, putc_unlocked, putchar_unlocked])
AC_OUTPUT(Makefile)
diff --git a/getline.h b/getline.h
new file mode 100644
index 0000000..ee9fc05
--- /dev/null
+++ b/getline.h
@@ -0,0 +1,39 @@
+/* Replacement for GNU C library function getline
+
+ Copyright (C) 1995, 1997, 1999, 2000, 2001, 2002, 2003 Free
+ Software Foundation, Inc.
+
+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, 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. */
+
+#ifndef GETLINE_H_
+# define GETLINE_H_ 1
+
+# include <stddef.h>
+# include <stdio.h>
+
+/* Get ssize_t. */
+# include <sys/types.h>
+
+/* glibc2 has these functions declared in <stdio.h>. Avoid redeclarations. */
+# if __GLIBC__ < 2
+
+extern ssize_t getline (char **_lineptr, size_t *_linesize, FILE *_stream);
+
+extern ssize_t getdelim (char **_lineptr, size_t *_linesize, int _delimiter,
+ FILE *_stream);
+
+# endif
+
+#endif /* not GETLINE_H_ */
diff --git a/getpass.c b/getpass.c
new file mode 100644
index 0000000..c46966f
--- /dev/null
+++ b/getpass.c
@@ -0,0 +1,182 @@
+/* Copyright (C) 1992-2001, 2003 Free Software Foundation, Inc.
+ This file was part of the GNU C Library.
+
+ 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, 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. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if _LIBC
+# define HAVE_STDIO_EXT_H 1
+#endif
+
+#include <stdbool.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#if HAVE_STDIO_EXT_H
+# include <stdio_ext.h>
+#else
+# define __fsetlocking(stream, type) /* empty */
+#endif
+#if !_LIBC
+# include "getline.h"
+#endif
+
+#include <termios.h>
+#include <unistd.h>
+
+#if _LIBC
+# include <wchar.h>
+#endif
+
+#if _LIBC
+# define NOTCANCEL_MODE "c"
+#else
+# define NOTCANCEL_MODE
+#endif
+
+#if _LIBC
+# define flockfile(s) _IO_flockfile (s)
+# define funlockfile(s) _IO_funlockfile (s)
+#else
+# include "unlocked-io.h"
+#endif
+
+#if _LIBC
+# include <bits/libc-lock.h>
+#else
+# define __libc_cleanup_push(function, arg) /* empty */
+# define __libc_cleanup_pop(execute) /* empty */
+#endif
+
+#if !_LIBC
+# define __getline getline
+# define __tcgetattr tcgetattr
+#endif
+
+/* It is desirable to use this bit on systems that have it.
+ The only bit of terminal state we want to twiddle is echoing, which is
+ done in software; there is no need to change the state of the terminal
+ hardware. */
+
+#ifndef TCSASOFT
+# define TCSASOFT 0
+#endif
+
+static void
+call_fclose (void *arg)
+{
+ if (arg != NULL)
+ fclose (arg);
+}
+
+char *
+xgetpass (const char *prompt)
+{
+ FILE *tty;
+ FILE *in, *out;
+ struct termios s, t;
+ bool tty_changed;
+ char *buf = NULL;
+ size_t bufsize = 0;
+ ssize_t nread;
+
+ /* Try to write to and read from the terminal if we can.
+ If we can't open the terminal, use stderr and stdin. */
+
+ tty = fopen ("/dev/tty", "w+" NOTCANCEL_MODE);
+ if (tty == NULL)
+ {
+ in = stdin;
+ out = stderr;
+ }
+ else
+ {
+ /* We do the locking ourselves. */
+ __fsetlocking (tty, FSETLOCKING_BYCALLER);
+
+ out = in = tty;
+ }
+
+ /* Make sure the stream we opened is closed even if the thread is
+ canceled. */
+ __libc_cleanup_push (call_fclose, tty);
+
+ flockfile (out);
+
+ /* Turn echoing off if it is on now. */
+
+ if (__tcgetattr (fileno (in), &t) == 0)
+ {
+ /* Save the old one. */
+ s = t;
+ /* Tricky, tricky. */
+ t.c_lflag &= ~(ECHO|ISIG);
+ tty_changed = (tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0);
+ }
+ else
+ tty_changed = false;
+
+ /* Write the prompt. */
+#ifdef USE_IN_LIBIO
+ if (_IO_fwide (out, 0) > 0)
+ __fwprintf (out, L"%s", prompt);
+ else
+#endif
+ fputs_unlocked (prompt, out);
+ fflush_unlocked (out);
+
+ /* Read the password. */
+ errno = 0;
+ nread = __getline (&buf, &bufsize, in);
+
+ if (buf != NULL)
+ {
+ if (nread < 0)
+ {
+ free (buf);
+ buf = NULL;
+ }
+ else if ((nread > 0) && (buf[nread - 1] == '\n'))
+ {
+ /* Remove the newline. */
+ buf[nread - 1] = '\0';
+ }
+ }
+
+ if (tty_changed)
+ {
+ /* Write the newline that was not echoed. */
+#ifdef USE_IN_LIBIO
+ if (_IO_fwide (out, 0) > 0)
+ putwc_unlocked (L'\n', out);
+ else
+#endif
+ putc_unlocked ('\n', out);
+ /* Restore the original setting. */
+ (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &s);
+ }
+
+ funlockfile (out);
+
+ __libc_cleanup_pop (0);
+
+ call_fclose (tty);
+
+ return buf;
+}
diff --git a/getpass.h b/getpass.h
new file mode 100644
index 0000000..131947c
--- /dev/null
+++ b/getpass.h
@@ -0,0 +1,7 @@
+#ifndef GETPASS_H_
+#define GETPASS_H_
+
+char *
+xgetpass (const char *prompt);
+
+#endif /* GETPASS_H_ */
diff --git a/hashalot.1 b/hashalot.1
deleted file mode 100644
index 20ace86..0000000
--- a/hashalot.1
+++ /dev/null
@@ -1,42 +0,0 @@
-.TH HASHALOT 1 "09 Feb 2004"
-.SH NAME
-hashalot \- read a passphrase and print a hash
-.SH SYNOPSIS
-.B hashalot [ \-s SALT ] [ \-x ] [ \-n #BYTES ] HASHTYPE
-.br
-.B HASHTYPE [ \-s SALT ] [ \-x ] [ \-n #BYTES ]
-.SH DESCRIPTION
-.PP
-\fIhashalot\fP is a small tool that reads a passphrase from standard
-input, hashes it using the given hash type, and prints the result to
-standard output.
-.PP
-Supported values for \fIHASHTYPE\fP:
-.br
-.RS 8
-ripemd160 rmd160 rmd160compat sha256 sha384 sha512
-.RE
-.PP
-.SH OPTIONS
-.l
-The option
-.B \-s \fISALT\fP
-specifies an initialization vector to the hashing algorithm. You need
-this if you want to prevent identical passwords to map to identical
-hashes, which is a security risk.
-.PP
-If the
-.B \-x
-option is given then the hash will be printed as a string of hexadecimal
-digits.
-.PP
-The
-.B \-n
-option can be used to limit (or increase) the number of bytes output. The
-default is as appropriate for the specified hash algorithm: 20 bytes for
-RIPEMD160, 32 bytes for SHA256, etc. The default for the "rmd160compat"
-hash is 16 bytes, for compatibility with the old kerneli.org utilities.
-.SH AUTHOR
-Ben Slusky <sluskyb@paranoiacs.org>
-.PP
-This manual page was written by Matthias Urlichs <smurf@debian.org>.
diff --git a/hashalot.8 b/hashalot.8
new file mode 100644
index 0000000..20ace86
--- /dev/null
+++ b/hashalot.8
@@ -0,0 +1,42 @@
+.TH HASHALOT 1 "09 Feb 2004"
+.SH NAME
+hashalot \- read a passphrase and print a hash
+.SH SYNOPSIS
+.B hashalot [ \-s SALT ] [ \-x ] [ \-n #BYTES ] HASHTYPE
+.br
+.B HASHTYPE [ \-s SALT ] [ \-x ] [ \-n #BYTES ]
+.SH DESCRIPTION
+.PP
+\fIhashalot\fP is a small tool that reads a passphrase from standard
+input, hashes it using the given hash type, and prints the result to
+standard output.
+.PP
+Supported values for \fIHASHTYPE\fP:
+.br
+.RS 8
+ripemd160 rmd160 rmd160compat sha256 sha384 sha512
+.RE
+.PP
+.SH OPTIONS
+.l
+The option
+.B \-s \fISALT\fP
+specifies an initialization vector to the hashing algorithm. You need
+this if you want to prevent identical passwords to map to identical
+hashes, which is a security risk.
+.PP
+If the
+.B \-x
+option is given then the hash will be printed as a string of hexadecimal
+digits.
+.PP
+The
+.B \-n
+option can be used to limit (or increase) the number of bytes output. The
+default is as appropriate for the specified hash algorithm: 20 bytes for
+RIPEMD160, 32 bytes for SHA256, etc. The default for the "rmd160compat"
+hash is 16 bytes, for compatibility with the old kerneli.org utilities.
+.SH AUTHOR
+Ben Slusky <sluskyb@paranoiacs.org>
+.PP
+This manual page was written by Matthias Urlichs <smurf@debian.org>.
diff --git a/hashalot.c b/hashalot.c
index 8823dea..c31ec4a 100644
--- a/hashalot.c
+++ b/hashalot.c
@@ -6,77 +6,89 @@
** an encryption key.
**
** USAGE:
-** hashalot [ -x ] [ -s _salt_ ] [ -n _#bytes_ ] _hashtype_
+** hashalot [ -q ] [ -x ] [ -s _salt_ ] [ -n _#bytes_ ] _hashtype_
** OR
-** _hashtype_ [ -x ] [ -s _salt_ ] [ -n _#bytes_ ]
+** _hashtype_ [ -q ] [ -x ] [ -s _salt_ ] [ -n _#bytes_ ]
**
** Most of the code was cribbed from the kerneli.org patch to util-linux,
** by Marc Mutz <Marc@Mutz.com>. Most of what wasn't, was cribbed from GnuPG,
** v.1.0.3 (http://www.gnupg.org/).
*/
-#include <libgen.h>
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <assert.h>
+#include <errno.h>
+#include <error.h>
#include <sys/types.h>
#include <sys/mman.h>
#include "rmd160.h"
#include "sha512.h"
+#include "getpass.h"
#define PASSWDBUFFLEN 130
-typedef int (*phash_func_t)(char dest[], size_t dest_len, const char src[], size_t src_len);
+const char *progname;
+
+typedef int (*phash_func_t) (char *dest, size_t dest_len,
+ const char *src, size_t src_len);
static int
-phash_rmd160(char dest[], size_t dest_len, const char src[], size_t src_len)
+phash_rmd160(char *dest, size_t dest_len, const char *src, size_t src_len)
{
- char tmp[PASSWDBUFFLEN] = { 'A', 0, };
- char key[RMD160_HASH_SIZE * 2] = { 0, };
+ char tmp[PASSWDBUFFLEN] = { 'A', 0, };
+ char key[RMD160_HASH_SIZE * 2] = { 0, };
+
+ strncat(tmp, src, sizeof(tmp) - 1);
- strncpy(tmp + 1, src, PASSWDBUFFLEN - 1);
- tmp[PASSWDBUFFLEN - 1] = '\0';
-
rmd160_hash_buffer(key, src, src_len);
- rmd160_hash_buffer(key + RMD160_HASH_SIZE, tmp, src_len + 1 /* dangerous! */);
+ rmd160_hash_buffer(key + RMD160_HASH_SIZE, tmp,
+ src_len + 1 /* dangerous! */ );
memcpy(dest, key, dest_len);
- memset (tmp, 0, PASSWDBUFFLEN); /* paranoia */
- memset (key, 0, RMD160_HASH_SIZE * 2); /* paranoia */
+ memset(tmp, 0, sizeof tmp); /* paranoia */
+ memset(key, 0, sizeof key); /* paranoia */
return dest_len;
}
static int
-phash_sha256(char dest[], size_t dest_len, const char src[], size_t src_len)
+phash_sha256(char *dest, size_t dest_len, const char *src, size_t src_len)
{
memset(dest, 0, dest_len);
- sha256_hash_buffer((char *) src, src_len, dest, dest_len);
+ sha256_hash_buffer((const unsigned char *) src, src_len,
+ (unsigned char *) dest, dest_len);
return dest_len;
}
static int
-phash_sha384(char dest[], size_t dest_len, const char src[], size_t src_len)
+phash_sha384(char *dest, size_t dest_len, const char *src, size_t src_len)
{
memset(dest, 0, dest_len);
- sha384_hash_buffer((char *) src, src_len, dest, dest_len);
+ sha384_hash_buffer((const unsigned char *) src, src_len,
+ (unsigned char *) dest, dest_len);
return dest_len;
}
static int
-phash_sha512(char dest[], size_t dest_len, const char src[], size_t src_len)
+phash_sha512(char *dest, size_t dest_len, const char *src, size_t src_len)
{
memset(dest, 0, dest_len);
- sha512_hash_buffer((char *) src, src_len, dest, dest_len);
+ sha512_hash_buffer((const unsigned char *) src, src_len,
+ (unsigned char *) dest, dest_len);
return dest_len;
}
-struct func_table_t {
+struct func_table_t
+{
const char *name;
phash_func_t func;
size_t def_length;
@@ -90,197 +102,204 @@ struct func_table_t {
{ 0, 0, 0 }
};
-static int
-show_usage(const char argv0[])
+static int __attribute__ ((__noreturn__))
+show_usage(void)
{
struct func_table_t *p = func_table;
- fprintf (stderr,
- "usage:\n"
- " hashalot [ -x ] [ -s SALT ] [ -n _#bytes_ ] HASHTYPE\n"
- " or\n"
- " HASHTYPE [ -x ] [ -s SALT ] [ -n _#bytes_ ]\n"
- "\n"
- "supported values for HASHTYPE: ");
+ fprintf(stderr,
+ "usage:\n"
+ " hashalot [ -q ] [ -x ] [ -s SALT ] [ -n _#bytes_ ] HASHTYPE\n"
+ " or\n"
+ " HASHTYPE [ -q ] [ -x ] [ -s SALT ] [ -n _#bytes_ ]\n"
+ "\n" "supported values for HASHTYPE:");
for (; p->name; ++p)
- fprintf (stderr, "%s ", p->name);
+ fprintf(stderr, " %s", p->name);
+
+ fprintf(stderr, "\n");
- fprintf (stderr, "\n");
-
- return 1;
+ exit(EXIT_FAILURE);
}
-static phash_func_t
-phash_lookup(const char phash_name[], size_t *length)
+static phash_func_t
+phash_lookup(const char *phash_name, size_t *length)
{
struct func_table_t *p = func_table;
if (!phash_name)
return 0;
- for (; p->name && strcmp(phash_name, p->name); ++p);
-
- if (length) *length = p->def_length;
+ for (; p->name && strcmp(phash_name, p->name); ++p)
+ ;
+ if (length)
+ *length = p->def_length;
return p->func;
}
-/* A function to read the passphrase either from the terminal or from
- * an open file descriptor */
static char *
-xgetpass(const char *prompt)
+zeroize(char *str)
{
- if (isatty(STDIN_FILENO)) /* terminal */
- return getpass(prompt); /* FIXME getpass(3) obsolete */
- else { /* file descriptor */
- char *pass = NULL;
- int buflen, i;
-
- buflen=0;
- for (i=0; ; i++) {
- if (i >= buflen - 1) {
- /* we're running out of space in the buffer.
- * Make it bigger: */
- char *tmppass = pass;
- buflen += 128;
- pass = (char *) realloc(tmppass, buflen);
- if (pass == NULL) {
- /* realloc failed. Stop reading _now_. */
- fprintf(stderr, "not enough memory while reading passphrase\n");
- pass = tmppass; /* the old buffer hasn't changed */
- break;
- }
- }
- if (read(STDIN_FILENO, pass+i, 1) != 1 || pass[i] == '\n')
- break;
- }
- if (pass == NULL)
- return "";
- else {
- pass[i] = 0;
- return pass;
- }
- }
-}
-
-static void *
-xmalloc (size_t size) {
- void *p;
-
- if (size == 0)
- return NULL;
+ char *p = str;
- p = malloc(size);
- if (p == NULL) {
- perror("malloc");
- exit(1);
- }
-
- return p;
+ while (*p)
+ *p++ = '\0';
+ return str;
}
/* function to append a "salt" to the passphrase, to better resist
* dictionary attacks */
static char *
-salt_passphrase(char *pass, char *salt) {
- char *buf = xmalloc(strlen(pass) + strlen(salt) + 1);
- sprintf(buf, "%s%s", pass, salt);
+salt_passphrase(char *pass, const char *salt)
+{
+ char *buf;
+ int rc;
- memset (pass, 0, strlen (pass)); /* paranoia */
- free(pass);
+ rc = asprintf(&buf, "%s%s", pass, salt);
+ zeroize(pass);
+ if (rc < 0)
+ error(EXIT_FAILURE, errno, "asprintf");
+ free(pass);
return buf;
}
+static void *
+xmalloc(size_t size)
+{
+ void *r = malloc(size);
+
+ if (!r)
+ error(EXIT_FAILURE, errno, "malloc");
+ return r;
+}
+
static void
-hexify(char *hash, size_t hashlen) {
- int i;
- char *h = xmalloc(hashlen);
- memcpy(h, hash, hashlen);
+hexify(char *hash, size_t hashlen)
+{
+ int i;
+ char *h = xmalloc(hashlen);
- for (i=0; i < hashlen; i++)
- snprintf((hash + 2*i), 3, "%.2x", (unsigned char) h[i]);
+ memcpy(h, hash, hashlen);
+ for (i = 0; i < hashlen; i++)
+ snprintf((hash + 2 * i), 3, "%.2x", (unsigned char) h[i]);
strcat(hash, "\n");
- memset(h, 0, hashlen); /* paranoia */
+ memset(h, 0, hashlen); /* paranoia */
free(h);
}
+static int
+write_loop(int fd, const char *buffer, size_t count)
+{
+ ssize_t offset = 0;
+
+ while (count > 0)
+ {
+ ssize_t block = write(fd, &buffer[offset], count);
+
+ if (block < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ return block;
+ }
+ if (!block)
+ break;
+ offset += block;
+ count -= block;
+ }
+ return offset;
+}
+
int
-main(int argc, char *argv[])
+main(int argc, char *argv[])
{
- char *pass, *passhash, *salt = NULL, *p;
- size_t hashlen = 0;
+ char *pass, *passhash, *salt = NULL, *p;
+ size_t hashlen = 0;
phash_func_t func;
- int hex_output = 0, c;
-
- while ((c = getopt(argc, argv, "n:s:x")) != -1) {
- switch (c) {
- case 'n':
- hashlen = strtoul(optarg, &p, 0);
- if (*p != '\0' || *optarg == '\0') {
- fprintf (stderr,
- "%s: argument to -n option must be numeric\n",
- argv[0]);
- show_usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- break;
- case 's':
- salt = optarg;
- break;
- case 'x':
- hex_output++;
- break;
- default:
- show_usage(argv[0]);
- exit(EXIT_FAILURE);
- }
+ int quiet = 0, hex_output = 0, c;
+ int rc = EXIT_SUCCESS;
+
+ progname = (argc > 0) ? basename(argv[0]) : "hashalot";
+
+ while ((c = getopt(argc, argv, "n:qs:x")) != -1)
+ {
+ switch (c)
+ {
+ case 'n':
+ hashlen = strtoul(optarg, &p, 0);
+ if (*p != '\0' || *optarg == '\0')
+ {
+ fprintf(stderr,
+ "%s: argument to -n option must be numeric\n",
+ progname);
+ show_usage();
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'q':
+ quiet = 1;
+ break;
+ case 's':
+ salt = optarg;
+ break;
+ case 'x':
+ hex_output = 1;
+ break;
+ default:
+ return EXIT_FAILURE;
+ }
}
- if (!(func = phash_lookup(basename(argv[0]), (hashlen ? NULL : &hashlen))))
+ if (!(func = phash_lookup(progname, (hashlen ? NULL : &hashlen))))
+ {
/* lookup failed, so try next argv */
- if (!(func = phash_lookup(argv[optind], (hashlen ? NULL : &hashlen)))) {
- /* lookup failed again */
- fprintf (stderr,
- "%s: missing or unknown hash type requested\n",
- argv[0]);
- show_usage(argv[0]);
- exit(EXIT_FAILURE);
- }
-
- assert (func != 0);
+ if (optind + 1 != argc)
+ show_usage();
+ func = phash_lookup(argv[optind],
+ (hashlen ? NULL : &hashlen));
+ if (!func)
+ {
+ /* lookup failed again */
+ fprintf(stderr,
+ "%s: missing or unknown hash type requested\n",
+ progname);
+ show_usage();
+ }
+ }
/* allocate memory for the password hash:
* enough for 2 hex digits per byte of the requested hash length,
* plus a newline, plus a null */
- passhash = xmalloc(2*hashlen + 2);
+ passhash = xmalloc(2 * hashlen + 2);
/* try to lock memory so it doesn't get swapped out for sure */
- if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
- perror("mlockall");
- fputs("Warning: couldn't lock memory, are you root?\n", stderr);
- }
+ if (mlockall(MCL_CURRENT | MCL_FUTURE) && !quiet)
+ error(EXIT_SUCCESS, errno, "failed to lock memory");
/* here we acquire the precious passphrase... */
- pass = xgetpass("Enter passphrase: ");
+ if (!(pass = xgetpass("Enter passphrase: ")))
+ error(EXIT_FAILURE, errno, "getpass failed");
if (salt)
pass = salt_passphrase(pass, salt);
hashlen = func(passhash, hashlen, pass, strlen(pass));
- memset (pass, 0, strlen (pass)); /* paranoia */
- free(pass);
+ free(zeroize(pass));
- if (hex_output) {
+ if (hex_output)
+ {
hexify(passhash, hashlen);
hashlen = hashlen * 2 + 1;
}
- if (write(STDOUT_FILENO, passhash, hashlen) != hashlen)
- perror("write");
+ if (write_loop(STDOUT_FILENO, passhash, hashlen) != hashlen)
+ {
+ error(EXIT_SUCCESS, errno, "write");
+ rc = EXIT_FAILURE;
+ }
- memset (passhash, 0, hashlen); /* paranoia again */
+ memset(passhash, 0, hashlen); /* paranoia again */
free(passhash);
- exit(EXIT_SUCCESS);
+ return rc;
}
-
diff --git a/sha512.c b/sha512.c
index a795228..e8f72bd 100644
--- a/sha512.c
+++ b/sha512.c
@@ -104,7 +104,7 @@ void sha256_init(sha256_context *ctx)
#define lSig0(x) ((S(7,(x))) ^ (S(18,(x))) ^ (R(3,(x))))
#define lSig1(x) ((S(17,(x))) ^ (S(19,(x))) ^ (R(10,(x))))
-static void sha256_transform(sha256_context *ctx, unsigned char *datap)
+static void sha256_transform(sha256_context *ctx, const unsigned char *datap)
{
register int j;
u_int32_t a, b, c, d, e, f, g, h;
@@ -157,7 +157,7 @@ static void sha256_transform(sha256_context *ctx, unsigned char *datap)
ctx->sha_blocks++;
}
-void sha256_write(sha256_context *ctx, unsigned char *datap, int length)
+void sha256_write(sha256_context *ctx, const unsigned char *datap, int length)
{
while(length > 0) {
if(!ctx->sha_bufCnt) {
@@ -221,7 +221,7 @@ void sha256_final(sha256_context *ctx)
memset(&ctx->sha_out[32], 0, sizeof(sha256_context) - 32);
}
-void sha256_hash_buffer(unsigned char *ib, int ile, unsigned char *ob, int ole)
+void sha256_hash_buffer(const unsigned char *ib, int ile, unsigned char *ob, int ole)
{
sha256_context ctx;
@@ -259,7 +259,7 @@ void sha512_init(sha512_context *ctx)
#define lSig0(x) ((S(1,(x))) ^ (S(8,(x))) ^ (R(7,(x))))
#define lSig1(x) ((S(19,(x))) ^ (S(61,(x))) ^ (R(6,(x))))
-static void sha512_transform(sha512_context *ctx, unsigned char *datap)
+static void sha512_transform(sha512_context *ctx, const unsigned char *datap)
{
register int j;
u_int64_t a, b, c, d, e, f, g, h;
@@ -315,7 +315,7 @@ static void sha512_transform(sha512_context *ctx, unsigned char *datap)
if(!ctx->sha_blocks) ctx->sha_blocksMSB++;
}
-void sha512_write(sha512_context *ctx, unsigned char *datap, int length)
+void sha512_write(sha512_context *ctx, const unsigned char *datap, int length)
{
while(length > 0) {
if(!ctx->sha_bufCnt) {
@@ -392,7 +392,7 @@ void sha512_final(sha512_context *ctx)
memset(&ctx->sha_out[64], 0, sizeof(sha512_context) - 64);
}
-void sha512_hash_buffer(unsigned char *ib, int ile, unsigned char *ob, int ole)
+void sha512_hash_buffer(const unsigned char *ib, int ile, unsigned char *ob, int ole)
{
sha512_context ctx;
@@ -416,7 +416,7 @@ void sha384_init(sha512_context *ctx)
ctx->sha_bufCnt = 0;
}
-void sha384_hash_buffer(unsigned char *ib, int ile, unsigned char *ob, int ole)
+void sha384_hash_buffer(const unsigned char *ib, int ile, unsigned char *ob, int ole)
{
sha512_context ctx;
diff --git a/sha512.h b/sha512.h
index 817dc26..5f5e4fc 100644
--- a/sha512.h
+++ b/sha512.h
@@ -28,18 +28,18 @@ typedef struct {
/* 256 bit hash, provides 128 bits of security against collision attacks */
extern void sha256_init(sha256_context *);
-extern void sha256_write(sha256_context *, unsigned char *, int);
+extern void sha256_write(sha256_context *, const unsigned char *, int);
extern void sha256_final(sha256_context *);
-extern void sha256_hash_buffer(unsigned char *, int, unsigned char *, int);
+extern void sha256_hash_buffer(const unsigned char *, int, unsigned char *, int);
/* 512 bit hash, provides 256 bits of security against collision attacks */
extern void sha512_init(sha512_context *);
-extern void sha512_write(sha512_context *, unsigned char *, int);
+extern void sha512_write(sha512_context *, const unsigned char *, int);
extern void sha512_final(sha512_context *);
-extern void sha512_hash_buffer(unsigned char *, int, unsigned char *, int);
+extern void sha512_hash_buffer(const unsigned char *, int, unsigned char *, int);
/* 384 bit hash, provides 192 bits of security against collision attacks */
extern void sha384_init(sha512_context *);
/* no sha384_write(), use sha512_write() */
/* no sha384_final(), use sha512_final(), result in ctx->sha_out[0...47] */
-extern void sha384_hash_buffer(unsigned char *, int, unsigned char *, int);
+extern void sha384_hash_buffer(const unsigned char *, int, unsigned char *, int);
diff --git a/unlocked-io.h b/unlocked-io.h
new file mode 100644
index 0000000..36a7a48
--- /dev/null
+++ b/unlocked-io.h
@@ -0,0 +1,132 @@
+/* Prefer faster, non-thread-safe stdio functions if available.
+
+ Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+
+ 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, 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. */
+
+/* Written by Jim Meyering. */
+
+#ifndef UNLOCKED_IO_H
+# define UNLOCKED_IO_H 1
+
+# ifndef USE_UNLOCKED_IO
+# define USE_UNLOCKED_IO 1
+# endif
+
+# if USE_UNLOCKED_IO
+
+/* These are wrappers for functions/macros from the GNU C library, and
+ from other C libraries supporting POSIX's optional thread-safe functions.
+
+ The standard I/O functions are thread-safe. These *_unlocked ones are
+ more efficient but not thread-safe. That they're not thread-safe is
+ fine since all of the applications in this package are single threaded.
+
+ Also, some code that is shared with the GNU C library may invoke
+ the *_unlocked functions directly. On hosts that lack those
+ functions, invoke the non-thread-safe versions instead. */
+
+# include <stdio.h>
+
+# if HAVE_DECL_CLEARERR_UNLOCKED
+# undef clearerr
+# define clearerr(x) clearerr_unlocked (x)
+# else
+# define clearerr_unlocked(x) clearerr (x)
+# endif
+# if HAVE_DECL_FEOF_UNLOCKED
+# undef feof
+# define feof(x) feof_unlocked (x)
+# else
+# define feof_unlocked(x) feof (x)
+# endif
+# if HAVE_DECL_FERROR_UNLOCKED
+# undef ferror
+# define ferror(x) ferror_unlocked (x)
+# else
+# define ferror_unlocked(x) ferror (x)
+# endif
+# if HAVE_DECL_FFLUSH_UNLOCKED
+# undef fflush
+# define fflush(x) fflush_unlocked (x)
+# else
+# define fflush_unlocked(x) fflush (x)
+# endif
+# if HAVE_DECL_FGETS_UNLOCKED
+# undef fgets
+# define fgets(x,y,z) fgets_unlocked (x,y,z)
+# else
+# define fgets_unlocked(x,y,z) fgets (x,y,z)
+# endif
+# if HAVE_DECL_FPUTC_UNLOCKED
+# undef fputc
+# define fputc(x,y) fputc_unlocked (x,y)
+# else
+# define fputc_unlocked(x,y) fputc (x,y)
+# endif
+# if HAVE_DECL_FPUTS_UNLOCKED
+# undef fputs
+# define fputs(x,y) fputs_unlocked (x,y)
+# else
+# define fputs_unlocked(x,y) fputs (x,y)
+# endif
+# if HAVE_DECL_FREAD_UNLOCKED
+# undef fread
+# define fread(w,x,y,z) fread_unlocked (w,x,y,z)
+# else
+# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
+# endif
+# if HAVE_DECL_FWRITE_UNLOCKED
+# undef fwrite
+# define fwrite(w,x,y,z) fwrite_unlocked (w,x,y,z)
+# else
+# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
+# endif
+# if HAVE_DECL_GETC_UNLOCKED
+# undef getc
+# define getc(x) getc_unlocked (x)
+# else
+# define getc_unlocked(x) getc (x)
+# endif
+# if HAVE_DECL_GETCHAR_UNLOCKED
+# undef getchar
+# define getchar() getchar_unlocked ()
+# else
+# define getchar_unlocked() getchar ()
+# endif
+# if HAVE_DECL_PUTC_UNLOCKED
+# undef putc
+# define putc(x,y) putc_unlocked (x,y)
+# else
+# define putc_unlocked(x,y) putc (x,y)
+# endif
+# if HAVE_DECL_PUTCHAR_UNLOCKED
+# undef putchar
+# define putchar(x) putchar_unlocked (x)
+# else
+# define putchar_unlocked(x) putchar (x)
+# endif
+
+# undef flockfile
+# define flockfile(x) ((void) 0)
+
+# undef ftrylockfile
+# define ftrylockfile(x) 0
+
+# undef funlockfile
+# define funlockfile(x) ((void) 0)
+
+# endif /* USE_UNLOCKED_IO */
+#endif /* UNLOCKED_IO_H */