/*
- * $Id: uams_randnum.c,v 1.14 2003-06-11 07:14:12 srittau Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
#include <stdio.h>
#include <stdlib.h>
-
-/* STDC check */
-#if STDC_HEADERS
#include <string.h>
-#else /* STDC_HEADERS */
-#ifndef HAVE_STRCHR
-#define strchr index
-#define strrchr index
-#endif /* HAVE_STRCHR */
-char *strchr (), *strrchr ();
-#ifndef HAVE_MEMCPY
-#define memcpy(d,s,n) bcopy ((s), (d), (n))
-#define memmove(d,s,n) bcopy ((s), (d), (n))
-#endif /* ! HAVE_MEMCPY */
-#endif /* STDC_HEADERS */
-
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif /* HAVE_FCNTL_H */
#include <ctype.h>
#include <pwd.h>
#include <sys/stat.h>
#include <sys/param.h>
+#include <arpa/inet.h>
#include <atalk/logger.h>
-
-#include <netatalk/endian.h>
-
#include <atalk/afp.h>
#include <atalk/uam.h>
-#include <des.h>
+#include <des.h>
#ifdef USE_CRACKLIB
#include <crack.h>
#endif /* USE_CRACKLIB */
-#include "crypt.h"
-
-#ifndef __inline__
-#define __inline__
-#endif /* __inline__ */
-
#define PASSWDLEN 8
static C_Block seskey;
+static Key_schedule seskeysched;
static struct passwd *randpwd;
-static u_int8_t randbuf[8];
+static uint8_t randbuf[8];
/* hash to a 16-bit number. this will generate completely harmless
* warnings on 64-bit machines. */
/* handle ~/.passwd. courtesy of shirsch@ibm.net. */
-static __inline__ int home_passwd(const struct passwd *pwd,
- const char *path, const int pathlen,
- char *passwd, const int len,
+static int home_passwd(const struct passwd *pwd,
+ const char *path, const int pathlen _U_,
+ unsigned char *passwd, const int len,
const int set)
{
struct stat st;
* key file:
* key (in hex) */
#define PASSWD_ILLEGAL '*'
+#define unhex(x) (isdigit(x) ? (x) - '0' : toupper(x) + 10 - 'A')
static int afppasswd(const struct passwd *pwd,
const char *path, const int pathlen,
- char *passwd, int len,
+ unsigned char *passwd, int len,
const int set)
{
- u_int8_t key[DES_KEY_SZ*2];
+ uint8_t key[DES_KEY_SZ*2];
char buf[MAXPATHLEN + 1], *p;
+ Key_schedule schedule;
FILE *fp;
+ unsigned int i, j;
int keyfd = -1, err = 0;
off_t pos;
/* open the key file if it exists */
strcpy(buf, path);
- if (pathlen < sizeof(buf) - 5) {
+ if (pathlen < (int) sizeof(buf) - 5) {
strcat(buf, ".key");
keyfd = open(buf, O_RDONLY);
}
memset(buf, 0, sizeof(buf));
while (fgets(buf, sizeof(buf), fp)) {
if ((p = strchr(buf, ':'))) {
- if (strncmp(buf, pwd->pw_name, p - buf) == 0) {
+ if ( strlen(pwd->pw_name) == (p - buf) &&
+ strncmp(buf, pwd->pw_name, p - buf) == 0) {
p++;
if (*p == PASSWD_ILLEGAL) {
LOG(log_info, logtype_uams, "invalid password entry for %s", pwd->pw_name);
goto afppasswd_done;
afppasswd_found:
- if (!set)
- atalk_unhexify(p, sizeof(key), p, sizeof(key));
+ if (!set) {
+ /* convert to binary. */
+ for (i = j = 0; i < sizeof(key); i += 2, j++)
+ p[j] = (unhex(p[i]) << 4) | unhex(p[i + 1]);
+ if (j <= DES_KEY_SZ)
+ memset(p + j, 0, sizeof(key) - j);
+ }
if (keyfd > -1) {
- size_t len;
-
/* read in the hex representation of an 8-byte key */
read(keyfd, key, sizeof(key));
/* convert to binary key */
- len = strlen((char *) key);
- atalk_unhexify(key, len, key, len);
+ for (i = j = 0; i < strlen((char *) 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 (set) {
/* NOTE: this takes advantage of the fact that passwd doesn't
* get used after this call if it's being set. */
- err = atalk_encrypt(key, passwd, passwd);
+ ecb_encrypt((C_Block *) passwd, (C_Block *) passwd, schedule,
+ DES_ENCRYPT);
} else {
- err = atalk_decrypt(key, p, p);
+ /* decrypt the password */
+ ecb_encrypt((C_Block *) p, (C_Block *) p, schedule, DES_DECRYPT);
}
- memset(key, 0, sizeof(key));
-
- if (err)
- goto afppasswd_done;
+ memset(&schedule, 0, sizeof(schedule));
}
if (set) {
+ const unsigned char hextable[] = "0123456789ABCDEF";
struct flock lock;
int fd = fileno(fp);
/* convert to hex password */
- atalk_hexify(key, sizeof(key), passwd, DES_KEY_SZ);
+ for (i = j = 0; i < DES_KEY_SZ; i++, j += 2) {
+ key[j] = hextable[(passwd[i] & 0xF0) >> 4];
+ key[j + 1] = hextable[passwd[i] & 0x0F];
+ }
memcpy(p, key, sizeof(key));
/* get exclusive access to the user's password entry. we don't
* depending upon whether or not the password is in ~/.passwd
* or in a global location */
static int randpass(const struct passwd *pwd, const char *file,
- char *passwd, const int len, const int set)
+ unsigned char *passwd, const int len, const int set)
{
int i;
uid_t uid = geteuid();
return i;
}
-
/* randnum sends an 8-byte number and uses the user's password to
* check against the encrypted reply. */
-static int randnum_login(void *obj, struct passwd **uam_pwd,
- char *ibuf, int ibuflen,
- char *rbuf, int *rbuflen)
+static int rand_login(void *obj, char *username, int ulen, struct passwd **uam_pwd _U_,
+ char *ibuf _U_, size_t ibuflen _U_,
+ char *rbuf, size_t *rbuflen)
{
- char *username, *passwdfile;
- u_int16_t sessid;
- int len, ulen, err;
-
- *rbuflen = 0;
-
- if (uam_afpserver_option(obj, UAM_OPTION_USERNAME,
- (void *) &username, &ulen) < 0)
- return AFPERR_PARAM;
-
- len = UAM_PASSWD_FILENAME;
- if (uam_afpserver_option(obj, UAM_OPTION_PASSWDOPT,
- (void *) &passwdfile, &len) < 0)
- return AFPERR_PARAM;
- len = (unsigned char) *ibuf++;
- if ( len > ulen ) {
- return AFPERR_PARAM;
- }
- memcpy(username, ibuf, len );
- ibuf += len;
- username[ len ] = '\0';
- if ((unsigned long) ibuf & 1) /* padding */
- ++ibuf;
-
- if (( randpwd = uam_getname(username, ulen)) == NULL )
- return AFPERR_PARAM; /* unknown user */
+ char *passwdfile;
+ uint16_t sessid;
+ size_t len;
+ int err;
+
+ if (( randpwd = uam_getname(obj, username, ulen)) == NULL )
+ return AFPERR_NOTAUTH; /* unknown user */
LOG(log_info, logtype_uams, "randnum/rand2num login: %s", username);
if (uam_checkuser(randpwd) < 0)
return AFPERR_NOTAUTH;
+ len = UAM_PASSWD_FILENAME;
+ if (uam_afpserver_option(obj, UAM_OPTION_PASSWDOPT,
+ (void *) &passwdfile, &len) < 0)
+ return AFPERR_PARAM;
+
if ((err = randpass(randpwd, passwdfile, seskey,
sizeof(seskey), 0)) != AFP_OK)
return err;
/* check encrypted reply. we actually setup the encryption stuff
* here as the first part of randnum and rand2num are identical. */
static int randnum_logincont(void *obj, struct passwd **uam_pwd,
- char *ibuf, int ibuflen,
- char *rbuf, int *rbuflen)
+ char *ibuf, size_t ibuflen _U_,
+ char *rbuf _U_, size_t *rbuflen)
{
- int err = AFP_OK;
- u_int16_t sessid;
+ uint16_t sessid;
*rbuflen = 0;
ibuf += sizeof(sessid);
- err = atalk_encrypt(seskey, randbuf, randbuf);
+ /* encrypt. this saves a little space by using the fact that
+ * des can encrypt in-place without side-effects. */
+ key_sched((C_Block *) seskey, seskeysched);
memset(seskey, 0, sizeof(seskey));
- if (err)
- return err;
+ ecb_encrypt((C_Block *) randbuf, (C_Block *) randbuf,
+ seskeysched, DES_ENCRYPT);
+ memset(&seskeysched, 0, sizeof(seskeysched));
/* test against what the client sent */
if (memcmp( randbuf, ibuf, sizeof(randbuf) )) { /* != */
memset(randbuf, 0, sizeof(randbuf));
*uam_pwd = randpwd;
- return err;
+ return AFP_OK;
}
* and sends it back as part of the reply.
*/
static int rand2num_logincont(void *obj, struct passwd **uam_pwd,
- char *ibuf, int ibuflen,
- char *rbuf, int *rbuflen)
+ char *ibuf, size_t ibuflen _U_,
+ char *rbuf, size_t *rbuflen)
{
- int err = AFP_OK;
- CryptHandle crypt_handle;
- u_int16_t sessid;
- int i;
+ uint16_t sessid;
+ unsigned int i;
*rbuflen = 0;
seskey[i] <<= 1;
/* encrypt randbuf */
- err = atalk_encrypt_start(&crypt_handle, seskey);
- atalk_encrypt_do(crypt_handle, randbuf, randbuf);
+ key_sched((C_Block *) seskey, seskeysched);
+ memset(seskey, 0, sizeof(seskey));
+ ecb_encrypt( (C_Block *) randbuf, (C_Block *) randbuf,
+ seskeysched, DES_ENCRYPT);
/* test against client's reply */
if (memcmp(randbuf, ibuf, sizeof(randbuf))) { /* != */
memset(randbuf, 0, sizeof(randbuf));
+ memset(&seskeysched, 0, sizeof(seskeysched));
return AFPERR_NOTAUTH;
}
ibuf += sizeof(randbuf);
memset(randbuf, 0, sizeof(randbuf));
/* encrypt client's challenge and send back */
- atalk_encrypt_do(crypt_handle, rbuf, ibuf);
- atalk_encrypt_end(crypt_handle);
- memset(seskey, 0, sizeof(seskey));
-
+ ecb_encrypt( (C_Block *) ibuf, (C_Block *) rbuf,
+ seskeysched, DES_ENCRYPT);
+ memset(&seskeysched, 0, sizeof(seskeysched));
*rbuflen = sizeof(randbuf);
*uam_pwd = randpwd;
* NOTE: an FPLogin must already have completed successfully for this
* to work.
*/
-static int randnum_changepw(void *obj, const char *username,
+static int randnum_changepw(void *obj, const char *username _U_,
struct passwd *pwd, char *ibuf,
- int ibuflen, char *rbuf, int *rbuflen)
+ size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen _U_)
{
char *passwdfile;
- int err, len;
+ int err;
+ size_t len;
if (uam_checkuser(pwd) < 0)
return AFPERR_ACCESS;
return err;
/* use old passwd to decrypt new passwd */
+ key_sched((C_Block *) seskey, seskeysched);
ibuf += PASSWDLEN; /* new passwd */
ibuf[PASSWDLEN] = '\0';
- err = atalk_decrypt(seskey, ibuf, ibuf);
- if (err)
- return err;
+ ecb_encrypt( (C_Block *) ibuf, (C_Block *) ibuf, seskeysched, DES_DECRYPT);
/* now use new passwd to decrypt old passwd */
+ key_sched((C_Block *) ibuf, seskeysched);
ibuf -= PASSWDLEN; /* old passwd */
- err = atalk_decrypt(ibuf, ibuf, ibuf);
- if (err)
- return err;
+ ecb_encrypt((C_Block *) ibuf, (C_Block *) ibuf, seskeysched, DES_DECRYPT);
if (memcmp(seskey, ibuf, sizeof(seskey)))
err = AFPERR_NOTAUTH;
else if (memcmp(seskey, ibuf + PASSWDLEN, sizeof(seskey)) == 0)
#endif /* USE_CRACKLIB */
if (!err)
- err = randpass(pwd, passwdfile, ibuf + PASSWDLEN, sizeof(seskey), 1);
+ err = randpass(pwd, passwdfile, (unsigned char *)ibuf + PASSWDLEN, sizeof(seskey), 1);
/* zero out some fields */
+ memset(&seskeysched, 0, sizeof(seskeysched));
memset(seskey, 0, sizeof(seskey));
memset(ibuf, 0, sizeof(seskey)); /* old passwd */
memset(ibuf + PASSWDLEN, 0, sizeof(seskey)); /* new passwd */
return( AFP_OK );
}
+/* randnum login */
+static int randnum_login(void *obj, struct passwd **uam_pwd,
+ char *ibuf, size_t ibuflen,
+ char *rbuf, size_t *rbuflen)
+{
+ char *username;
+ size_t len, ulen;
+
+ *rbuflen = 0;
+
+ if (uam_afpserver_option(obj, UAM_OPTION_USERNAME,
+ (void *) &username, &ulen) < 0)
+ return AFPERR_MISC;
+
+ if (ibuflen < 2) {
+ return( AFPERR_PARAM );
+ }
+
+ len = (unsigned char) *ibuf++;
+ ibuflen--;
+ if (!len || len > ibuflen || len > ulen ) {
+ return( AFPERR_PARAM );
+ }
+ memcpy(username, ibuf, len );
+ ibuf += len;
+ ibuflen -=len;
+ username[ len ] = '\0';
+
+ if ((unsigned long) ibuf & 1) { /* pad character */
+ ++ibuf;
+ ibuflen--;
+ }
+ return (rand_login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen));
+}
+
+/* randnum login ext */
+static int randnum_login_ext(void *obj, char *uname, struct passwd **uam_pwd,
+ char *ibuf, size_t ibuflen,
+ char *rbuf, size_t *rbuflen)
+{
+ char *username;
+ size_t len, ulen;
+ uint16_t temp16;
+
+ *rbuflen = 0;
+
+ if (uam_afpserver_option(obj, UAM_OPTION_USERNAME,
+ (void *) &username, &ulen) < 0)
+ return AFPERR_MISC;
+
+ if (*uname != 3)
+ return AFPERR_PARAM;
+ uname++;
+ memcpy(&temp16, uname, sizeof(temp16));
+ len = ntohs(temp16);
+ if (!len || len > ulen ) {
+ return( AFPERR_PARAM );
+ }
+ memcpy(username, uname +2, len );
+ username[ len ] = '\0';
+ return (rand_login(obj, username, ulen, uam_pwd, ibuf, ibuflen, rbuf, rbuflen));
+}
+
static int uam_setup(const char *path)
{
- if (uam_register(UAM_SERVER_LOGIN, path, "Randnum exchange",
- randnum_login, randnum_logincont, NULL) < 0)
+ if (uam_register(UAM_SERVER_LOGIN_EXT, path, "Randnum exchange",
+ randnum_login, randnum_logincont, NULL, randnum_login_ext) < 0)
return -1;
- if (uam_register(UAM_SERVER_LOGIN, path, "2-Way Randnum exchange",
- randnum_login, rand2num_logincont, NULL) < 0) {
+
+ if (uam_register(UAM_SERVER_LOGIN_EXT, path, "2-Way Randnum exchange",
+ randnum_login, rand2num_logincont, NULL, randnum_login_ext) < 0) {
uam_unregister(UAM_SERVER_LOGIN, "Randnum exchange");
return -1;
}
-
+
if (uam_register(UAM_SERVER_CHANGEPW, path, "Randnum Exchange",
randnum_changepw) < 0) {
uam_unregister(UAM_SERVER_LOGIN, "Randnum exchange");