/*
- * $Id: afppasswd.c,v 1.12 2003-06-06 22:34:34 srittau Exp $
+ * $Id: afppasswd.c,v 1.18 2003-06-09 02:55:25 srittau Exp $
*
* Copyright 1999 (c) Adrian Sun (asun@u.washington.edu)
* All Rights Reserved. See COPYRIGHT.
#include <config.h>
#endif /* HAVE_CONFIG_H */
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netatalk/endian.h>
+#if HAVE_GCRYPT
+#include <gcrypt.h>
+#define DES_KEY_SZ 8
+#else
#include <des.h>
+#endif
#ifdef USE_CRACKLIB
#include <crack.h>
#define OPTIONS "cafnu:p:"
#define UID_START 100
-#define HEXPASSWDLEN 16
-#define PASSWDLEN 8
+#define PASSWDLEN DES_KEY_SZ
+#define HEXPASSWDLEN (PASSWDLEN * 2)
static char buf[MAXPATHLEN + 1];
#define _(x) (x)
#endif
-/* if newpwd is null, convert buf from hex to binary. if newpwd isn't
- * null, convert newpwd to hex and save it in buf. */
-#define unhex(x) (isdigit(x) ? (x) - '0' : toupper(x) + 10 - 'A')
-static void convert_passwd(char *buf, char *newpwd, const int keyfd)
+/* SRC and DST must not overlap. */
+static void hexify(u_int8_t *dst, const u_int8_t *src)
{
- u_int8_t key[HEXPASSWDLEN];
- Key_schedule schedule;
int i, j;
- if (!newpwd) {
- /* convert to binary */
- for (i = j = 0; i < sizeof(key); i += 2, j++)
- buf[j] = (unhex(buf[i]) << 4) | unhex(buf[i + 1]);
- if (j <= DES_KEY_SZ)
- memset(buf + j, 0, sizeof(key) - j);
+ for (i = j = 0; i < DES_KEY_SZ; i++, j += 2) {
+ static const unsigned char hextable[] = "0123456789ABCDEF";
+
+ dst[j] = hextable[(src[i] & 0xF0) >> 4];
+ dst[j + 1] = hextable[(src[i] & 0x0F)];
}
+}
+
+/* SRC and DST can overlap. */
+#define unhex(x) (isdigit(x) ? (x) - '0' : toupper(x) + 10 - 'A')
+static void unhexify(u_int8_t *dst, const u_int8_t *src)
+{
+ int i, j;
+
+ /* convert to binary */
+ for (i = j = 0; i < HEXPASSWDLEN; i += 2, j++)
+ dst[j] = (unhex(src[i]) << 4) | unhex(src[i + 1]);
+ if (j <= DES_KEY_SZ)
+ memset(dst + j, 0, HEXPASSWDLEN - j);
+}
+
+static u_int8_t *retrieve_key(int keyfd)
+{
+ static u_int8_t key[HEXPASSWDLEN];
- if (keyfd > -1) {
- lseek(keyfd, 0, SEEK_SET);
- read(keyfd, key, sizeof(key));
- /* convert to binary */
- for (i = j = 0; i < sizeof(key); i += 2, j++)
- key[j] = (unhex(key[i]) << 4) | unhex(key[i + 1]);
- if (j <= DES_KEY_SZ)
- memset(key + j, 0, sizeof(key) - j);
- key_sched((C_Block *) key, schedule);
- memset(key, 0, sizeof(key));
- if (newpwd) {
- ecb_encrypt((C_Block *) newpwd, (C_Block *) newpwd, schedule,
- DES_ENCRYPT);
+ if (lseek(keyfd, 0, SEEK_SET) == -1)
+ return NULL;
+ if (read(keyfd, key, sizeof(key)) < sizeof(key))
+ return NULL;
+
+ unhexify(key, key);
+
+ return key;
+}
+
+static int decrypt_passwd(u_int8_t *dst, const u_int8_t *src, int keyfd)
+{
+ u_int8_t *key;
+ int err = 0;
+
+ key = retrieve_key(keyfd);
+ if (!key)
+ return 0;
+
+ {
+#if HAVE_GCRYPT
+ GcryCipherHd handle;
+
+ handle = gcry_cipher_open(GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ if (handle) {
+ int ret;
+
+ ret = gcry_cipher_setkey(handle, key, DES_KEY_SZ);
+ if (!ret)
+ ret = gcry_cipher_decrypt(handle, dst, 8, src, 8);
+ gcry_cipher_close(handle);
+ if (ret) {
+ fprintf(stderr, _("Decryption error: %s\n"), gcry_strerror(ret));
+ err = 1;
+ }
+ printf("pw: %s\n", buf); /* FIXME */
} else {
- /* decrypt the password */
- ecb_encrypt((C_Block *) buf, (C_Block *) buf, schedule, DES_DECRYPT);
+ fprintf(stderr, _("Could not create crypt handle.\n"));
+ err = 1;
}
- memset(&schedule, 0, sizeof(schedule));
+#else
+ DES_key_schedule schedule;
+
+ DES_set_key_unchecked((DES_cblock *) key, &schedule);
+ DES_ecb_encrypt((DES_cblock *) src, (DES_cblock *) dst,
+ &schedule, DES_DECRYPT);
+
+ memset(&schedule, 0, sizeof(schedule));
+#endif
}
- if (newpwd) {
- const unsigned char hextable[] = "0123456789ABCDEF";
+ memset(key, 0, HEXPASSWDLEN);
- /* convert to hex */
- for (i = j = 0; i < DES_KEY_SZ; i++, j += 2) {
- buf[j] = hextable[(newpwd[i] & 0xF0) >> 4];
- buf[j + 1] = hextable[newpwd[i] & 0x0F];
+ return err;
+}
+
+static int encrypt_passwd(u_int8_t *dst, const u_int8_t *src, int keyfd)
+{
+ const u_int8_t *key;
+ int err = 0;
+
+ key = retrieve_key(keyfd);
+ if (!key)
+ return 0;
+
+ {
+#if HAVE_GCRYPT
+ GcryCipherHd handle;
+ int ret;
+
+ handle = gcry_cipher_open(GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
+ if (handle) {
+ ret = gcry_cipher_setkey(handle, key, DES_KEY_SZ);
+ if (!ret)
+ ret = gcry_cipher_encrypt(handle, dst, 8, src, 0);
+ gcry_cipher_close(handle);
+ if (ret) {
+ fprintf(stderr, _("Encryption error: %s\n"), gcry_strerror(ret));
+ err = 1;
+ }
+ } else {
+ fprintf(stderr, _("Could not create crypt handle.\n"));
+ err = 1;
}
+#else
+ DES_key_schedule schedule;
+
+ DES_set_key_unchecked((DES_cblock *) key, &schedule);
+ DES_ecb_encrypt((DES_cblock *) src, (DES_cblock *) dst,
+ &schedule, DES_ENCRYPT);
+
+ memset(&schedule, 0, sizeof(schedule));
+#endif
}
+
+ return err;
}
/* this matches the code in uam_randnum.c */
if (strlen(path) < sizeof(buf) - 5) {
strcat(buf, ".key");
keyfd = open(buf, O_RDONLY);
+ if (keyfd == -1 && errno != ENOENT) {
+ fprintf(stderr, _("Can't open key file %s: %s\n"), buf, strerror(errno));
+ err = 1;
+ goto update_done;
+ }
}
pos = ftell(fp);
/* need to verify against old password */
if ((flags & OPT_ISROOT) == 0) {
passwd = getpass(_("Enter OLD AFP password: "));
- convert_passwd(p, NULL, keyfd);
+ unhexify(p, p);
+ err = decrypt_passwd(p, p, keyfd);
+ if (err) {
+ memset(passwd, 0, strlen(passwd));
+ goto update_done;
+ }
if (strncmp(passwd, p, PASSWDLEN)) {
memset(passwd, 0, strlen(passwd));
fprintf(stderr, _("Wrong password.\n"));
err = 1;
goto update_done;
}
+ memset(passwd, 0, strlen(passwd));
}
- memset(passwd, 0, strlen(passwd));
/* new password */
passwd = getpass(_("Enter NEW AFP password: "));
memset(passwd, 0, strlen(passwd));
- convert_passwd(p, password, keyfd);
+ err = encrypt_passwd(password, password, keyfd);
+ if (err)
+ goto update_done;
+ hexify(p, password);
+
lock.l_type = F_WRLCK;
lock.l_start = pos;
lock.l_len = 1;