Logo Search packages:      
Sourcecode: afbackup version File versions  Download package

crptauth.c

/****************** Start of $RCSfile: crptauth.c,v $  ****************
*
* $Source: /home/alb/afbackup/afbackup-3.3.8.1/RCS/crptauth.c,v $
* $Id: crptauth.c,v 1.3 2004/07/08 20:34:44 alb Exp alb $
* $Date: 2004/07/08 20:34:44 $
* $Author: alb $
*
*
******* description ***********************************************
*
*
*
*******************************************************************/

#include <conf.h>
#include <version.h>

  static char * fileversion = "$RCSfile: crptauth.c,v $ $Source: /home/alb/afbackup/afbackup-3.3.8.1/RCS/crptauth.c,v $ $Id: crptauth.c,v 1.3 2004/07/08 20:34:44 alb Exp alb $ " PACKAGE " " VERSION_STRING;

#include <unistd.h>
#include <fcntl.h>
#include <math.h>
#include <errno.h>
#include <sys/types.h>
#ifdef      HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <sys/stat.h>
#include <genutils.h>
#include <x_types.h>
#include <x_errno.h>
#include <crptauth.h>

#ifdef      HAVE_DES_ENCRYPTION
#include <des_aux.h>
#endif

#ifndef XOR
#define XOR(a,b)  (((a) & ~(b)) | (~(a) & (b)))
#endif

#ifndef     ETIMEDOUT
#define     ETIMEDOUT   EAGAIN
#endif

#define     LOGON_TIMEOUT     90


Int32
logon_to_server_k(
  int fromfd,
  int tofd,
  UChar     *greeting_message,
  UChar     *version_msg_key,
  UChar     **versionstr,
  Uns32     flags,
  void      *key)
{
  UChar           cbuf[30], buf[1000], *cptr;
  Int32           i;
  Flag            usedes, confirm;

  usedes = (flags & AUTH_USE_DES ? YES : NO);
  confirm = (flags & AUTH_NOCONFIRM ? NO : YES);

  memset(buf, 0, 1000 * sizeof(UChar));

  if(greeting_message){
    for(i = 0; i < 1000; i++){
      if(wait_for_input(fromfd, LOGON_TIMEOUT) < 1)
      return(NO_GREETING_MESSAGE);

      if(read_forced(fromfd, buf + i, 1) != 1){
      return(NO_GREETING_MESSAGE);
      }

      if(strstr(buf, greeting_message))
      break;
    }
    if(i >= 1000)
      return(NO_GREETING_MESSAGE);
  }

  if(versionstr && version_msg_key){
    *versionstr = NULL;

    cptr = strstr(buf, version_msg_key);
    if(cptr){
      cptr += strlen(version_msg_key);
      *versionstr = strword(cptr, 0);
    }
  }

  if(usedes){
#ifdef      HAVE_DES_ENCRYPTION
    read_forced(fromfd, cbuf, 16);

    encrpt_k(cbuf, usedes, key);

    write_forced(tofd, cbuf, 16);
#else

    fprintf(stderr, T_("Error: DES encryption not available.\n"));

    return( (errno = EINVAL) );
#endif
  }
  else{
    read_forced(fromfd, cbuf, 4);

    encrpt_k(cbuf, usedes, key);

    write_forced(tofd, cbuf, 4);
  }

  if(confirm){
    read_forced(fromfd, cbuf, 1);

    return((Int32) cbuf[0]);
  }

  return(0);
}

Int32
authenticate_client_k(
  int       tofd,
  int       fromfd,
  Flag            prot_only,
  UChar           *initmsg,
  UChar     fresult,
  UChar           errb,
  Uns32           flags,
  Int32           timeout_sec,
  void            *key)
{
  UChar           *cptr, buf[100], c = 0;
  Int32           i;
  Uns32           code;
  Flag            auth_ok, usedes, confirm;

  usedes = (flags & AUTH_USE_DES ? YES : NO);
  confirm = (flags & AUTH_NOCONFIRM ? NO : YES);

  cptr = initmsg;
  i = strlen(cptr);

  write_forced(tofd, cptr, i);

  if(usedes){
#ifdef      HAVE_DES_ENCRYPTION
    for(i = 0; i < 4; i++){
      code = (Uns32) (drandom() * 4294967296.0);
      memcpy(buf + 4 * i, &code, sizeof(Uns32));
    }
    write_forced(tofd, buf, 16);

    encrpt_k(buf, usedes, key);

    if(read_with_timeout(fromfd, buf + 16, 16, timeout_sec) < 0)
      return(errno = ETIMEDOUT);

    auth_ok = ! memcmp(buf, buf + 16, 16);
#else
    fprintf(stderr, T_("Error: DES encryption not available.\n"));

    return( (errno = EINVAL) );
#endif
  }
  else{
    code = (Uns32) (drandom() * 4294967296.0);

    Uns32_to_xref(buf, code);

    encrpt_k(buf, usedes, key);

    write_forced(tofd, buf, 4);

    encrpt_k(buf, usedes, key);

    if(read_with_timeout(fromfd, buf + 4, 4, timeout_sec) < 0)
      return(errno = ETIMEDOUT);

    auth_ok = ! memcmp(buf, buf + 4, 4);
  }

  if(!auth_ok && !prot_only)
    c = errb;

  if(fresult)
    c = fresult;

  if(confirm)
    write_forced(tofd, &c, 1);

  return((Int32) c);
}

Int32
check_cryptfile(UChar * filename)
{
  Int32           i;
  struct stat     statb;

  if(!filename)
    return(2);

  i = access(filename, R_OK);
  if(i)
    return(3);

  i = stat(filename, &statb);
  if(i)
    return(4);

  if(statb.st_mode & 0044)
    return(-1);

  if(statb.st_size < 5)
    return(1);

  return(0);
}

static UChar      *crmsg_warnings[] = {
            TN_ ("Key in file is too short"),
            TN_ ("No filename supplied"),
            TN_ ("File not readable"),
            TN_ ("Cannot get file information"),
            };
static UChar      *crmsg_errors[] = {
            TN_ ("File is group/world readable"),
            };

UChar *
check_cryptfile_msg(Int32 errn)
{
  if(errn > 0)
    return(T_(crmsg_warnings[errn - 1]));
  if(errn < 0)
    return(T_(crmsg_errors[- errn - 1]));

  return(NULL);
}


#ifdef      HAVE_DES_ENCRYPTION

static      UChar *initstring = "Albi's encryption initialization string";

static      des_key_schedule  accesskeys[2];

#else

static      void              *accesskeys;

#endif

static Int32
make_cryptkey_des(void * tgt, UChar * filename, UChar * keystr)
{
#ifdef      HAVE_DES_ENCRYPTION
  struct stat     statb;
  Int32           i, fd, ret = 0;
  Uns32           factor, prevval, newval;
  UChar           buf[100], *kptr, *endptr, *bufptr;
  des_cblock      rawkeys[2];
  des_key_schedule      keys[2];

  buf[0] = '\0';

  if(filename){
    i = stat(filename, &statb);
    if(i)
      ret = ENOENT;
    else{
      fd = open(filename, O_RDONLY);
      if(fd < 0){
      ret = EACCES;
      }
      else{
      i = read(fd, buf, 99);
      close(fd);

      if(i < 0)
        i = 0;
      buf[i] = '\0';
      }
    }
  }

  if(ret || !filename)
    strncpy(buf, keystr, 99);
  if(!buf[0])
    memset(buf, 0x5a, 99);
  buf[99] = '\0';

  memset(rawkeys, 0x5a, 2 * sizeof(des_cblock));
  kptr = (UChar *) &(rawkeys[0]);
  endptr = kptr + 2 * sizeof(des_cblock);
  bufptr = buf + 1;

  prevval = buf[0] % 0x40;
  factor = 0x40;
  forever{
    if(! *bufptr)
      break;

    newval = prevval + factor * ((*bufptr) % 0x40);
    factor *= 0x40;

    if((newval & 0xff) == (prevval & 0xff) && factor >= 0x0100){
      *kptr = (prevval & 0xff);
      kptr++;
      if(kptr >= endptr)
        break;

      factor /= 0x0100;
      newval /= 0x0100;
    }

    prevval = newval;
    bufptr++;
  }
  while(kptr < endptr && prevval){
    *(kptr++) = prevval & 0xff;
    prevval /= 0x0100;
  }

  if(des_set_key(rawkeys, keys[0])
                  || des_set_key(rawkeys + 1, keys[1]))
    ret = -1;

  memcpy(tgt, keys, 2 * sizeof(des_key_schedule));

  return(ret);

#else

  fprintf(stderr, T_("Error: DES encryption not available.\n"));

  return( (errno = EINVAL) );

#endif      /* defined(HAVE_DES_ENCRYPTION) */
}

static Int32
set_cryptkey_des(UChar * filename, UChar * keystr)
{
  return(make_cryptkey_des(accesskeys, filename, keystr));
}

static Uns32
encrpt_des_k(UChar * buf, void * key)
{
#ifdef      HAVE_DES_ENCRYPTION
  UChar           lbuf[20], mask, *cptr;
  des_cblock      ivec[2];
  Int32           i;
  des_key_schedule      *keys;

  keys = (des_key_schedule *) key;
  cptr = (UChar *) ivec;
  mask = 0xdf;

  for(i = 0; i < sizeof(des_cblock) * 2; i++, cptr++){
    *cptr = XOR(mask, initstring[i]);
    mask = XOR(mask, initstring[i]);
  }

#ifndef     LIBDESBUG_COMPATIBILITY
  des_ede2_cbc_encrypt((des_cblock *) buf, (des_cblock *) lbuf,
                  16 * sizeof(UChar),
                  keys[0], keys[1], ivec, 1);
#else
  des_3cbc_encrypt((des_cblock *) buf, (des_cblock *) lbuf,
                  16 * sizeof(UChar),
                  keys[0], keys[1], ivec, ivec + 1, 1);
#endif

  memcpy(buf, lbuf, 16 * sizeof(UChar));

  return(0);

#else

  fprintf(stderr, T_("Error: DES encryption not available.\n"));

  return( (errno = EINVAL) );

#endif      /* defined(HAVE_DES_ENCRYPTION) */
}

static Uns32
encrpt_des(UChar * buf)
{
  return(encrpt_des_k(buf, accesskeys));
}

static Int32
cryptn_des_k(UChar * buf, Int32 len, Flag en, void * key)
{
#ifdef      HAVE_DES_ENCRYPTION
  UChar           sbuf[4096], *tbuf = NULL, *cbuf, mask, *cptr;
  des_cblock      ivec[2];
  Int32           i, l;
  des_key_schedule      *keys;

  keys = (des_key_schedule *) key;

  cbuf = sbuf;
  l = (((len - 1) >> 4) + 1) << 4;

  if(l > 4096){
    tbuf = NEWP(UChar, l);
    if(!tbuf)
      return(-1);

    cbuf = tbuf;
  }

  cptr = (UChar *) ivec;
  mask = 0xdf;

  for(i = 0; i < sizeof(des_cblock) * 2; i++, cptr++){
    *cptr = XOR(mask, initstring[i]);
    mask = XOR(mask, initstring[i]);
  }

#ifndef     LIBDESBUG_COMPATIBILITY
  des_ede2_cbc_encrypt((des_cblock *) buf, (des_cblock *) cbuf,
                  l * sizeof(UChar),
                  keys[0], keys[1],
                  ivec, en ? 1 : 0);
#else
  des_3cbc_encrypt((des_cblock *) buf, (des_cblock *) cbuf,
                  l * sizeof(UChar),
                  keys[0], keys[1],
                  ivec, ivec + 1, en ? 1 : 0);
#endif

  memcpy(buf, cbuf, l * sizeof(UChar));

  if(tbuf)
    free(tbuf);

  return(0);


#else

  fprintf(stderr, T_("Error: DES encryption not available.\n"));

  return( (errno = EINVAL) );

#endif
}

static Int32
cryptn_des(UChar * buf, Int32 len, Flag en)
{
  return(cryptn_des_k(buf, len, en, accesskeys));
}

#define     PI_1_8            (M_PI / 8.0)
#define     PI_3_8            (M_PI / 8.0 * 3.0)
#define     S_PI_1_8    sin(PI_1_8)
#define     S_PI_3_8    sin(PI_3_8)

#define     LOG_8       log(8.0)
#define     LOG_12            log(12.0)

static Uns32      accesskey = 0;

static Int32
make_cryptkey_simple(void * tgt, UChar * filename, UChar * accesskeystr)
{
  struct stat     statb;
  Int32           i, fd;
  Uns32           n;
  UChar           buf[10];

  if(!accesskeystr)
    return(EINVAL);

  if(filename){
    i = stat(filename, &statb);
    if(i)
      return(ENOENT);

    fd = open(filename, O_RDONLY);
    if(fd < 0)
      return(EACCES);

    i = read(fd, buf, 5);
    close(fd);

    if(i < 5)
      return(EIO);
  }
  else
    memcpy(buf, accesskeystr, 5);

  n = 0;
  for(i = 0; i < 5; i++)
    n = (n * 96 + ((buf[i] & 0x7f) - 32)) & 0xffffffff;

  memcpy(tgt, &n, sizeof(n));

  return(0);
}

static Int32
set_cryptkey_simple(UChar * filename, UChar * accesskeystr)
{
  return(make_cryptkey_simple(&accesskey, filename, accesskeystr));
}

static Uns32
encrpt_simple_k(UChar * inptr, Uns32 key)
{
  Uns32           inp, a, b, in;

  xref_to_Uns32(&in, inptr);

  inp = XOR(in, key);

  a = inp >> 5;
  a &= (1 << 13) - 1;

  a = (Uns32) ((sin((double)a / 8192.0 * (PI_3_8 - PI_1_8) + PI_1_8)
                  - S_PI_1_8) / (S_PI_3_8 - S_PI_1_8) * 8192.0);

  b = a;

  a = inp & ((1 << 5) - 1);
  a = a * a * a;

  a &= ((1 << 5) - 1);

  b |= a << 13;

  a = (inp >> 18);
  a &= (1 << 9) - 1;

  a = (Uns32) ((log((double)a / 512.0 * 4.0 + 8.0) - LOG_8)
                  / (LOG_12 - LOG_8) * 512.0);

  b |= a << 23;

  a = (inp >> 27);
  a &= (1 << 5) - 1;

  a = (Uns32) ((4.0 - sqrt((double)a / 32.0 * 7.0 + 9.0)) * 32.0);

  b |= a << 18;

  Uns32_to_xref(inptr, b);

  return(b);
}

static Uns32
encrpt_simple(UChar * inptr)
{
  return(encrpt_simple_k(inptr, accesskey));
}

static Int32
cryptn_simple_k(UChar * buf, Int32 n, Uns32 key)
{
  for(; n > 0; buf += 4, n -= 4)
    encrpt_simple_k(buf, key);
   
  return(0); 
}

static Int32
cryptn_simple(UChar * buf, Int32 n)
{
  return(cryptn_simple_k(buf, n, accesskey)); 
}

Int32
nencrypt(UChar * buf, Int32 n, Flag usedes)
{
  if(usedes)
    return(cryptn_des(buf, n, YES));

  return(cryptn_simple(buf, n));
}

Int32
ndecrypt(UChar * buf, Int32 n, Flag usedes)
{
  if(usedes)
    return(cryptn_des(buf, n, NO));

  fprintf(stderr, T_("Error: not yet implemented.\n"));
  return(1);
}

Int32
nencrypt_k(UChar * buf, Int32 n, Flag usedes, void * key)
{
  if(usedes)
    return(cryptn_des_k(buf, n, YES, key));

  return(cryptn_simple_k(buf, n, *((UChar *) key)));
}

Int32
ndecrypt_k(UChar * buf, Int32 n, Flag usedes, void * key)
{
  if(usedes)
    return(cryptn_des_k(buf, n, NO, key));

  fprintf(stderr, T_("Error: not yet implemented.\n"));
  return(1);
}

Int32
set_cryptkey(UChar * filename, UChar * defkey, Flag usedes)
{
  if(usedes)
    return(set_cryptkey_des(filename, defkey));

  return(set_cryptkey_simple(filename, defkey));
}

Int32
make_cryptkey(void * tgt, UChar * filename, UChar * defkey, Flag usedes)
{
  if(usedes)
    return(make_cryptkey_des(tgt, filename, defkey));

  return(make_cryptkey_simple(tgt, filename, defkey));
}

Uns32
encrpt(UChar * data, Flag usedes)
{
  if(usedes)
    return(encrpt_des(data));

  return(encrpt_simple(data));
}

Uns32
encrpt_k(UChar * data, Flag usedes, void * key)
{
  if(usedes)
    return(encrpt_des_k(data, key));

  return(encrpt_simple_k(data, *((Uns32 *) key)));
}

Int32
sizeof_cryptkey(Flag usedes)
{
  if(usedes)

#ifdef      HAVE_DES_ENCRYPTION

    return(sizeof(des_key_schedule) * 2);

#else

    return(0);

#endif

  return(sizeof(Uns32));
}


Int32
logon_to_server(
  int fromfd,
  int tofd,
  UChar     *greeting_message,
  UChar     *version_msg_key,
  UChar     **versionstr,
  Uns32     flags)
{
  return(logon_to_server_k(fromfd, tofd, greeting_message, version_msg_key,
            versionstr, flags,
            ((flags & AUTH_USE_DES) ? accesskeys : (void *)(&accesskey))));
}

Int32
authenticate_client(
  int tofd,
  int fromfd,
  Flag      prot_only,
  UChar     *initmsg,
  UChar fresult,
  UChar     errb,
  Uns32     flags,
  Int32     timeout_sec)
{
  return(authenticate_client_k(tofd, fromfd, prot_only, initmsg, fresult,
            errb, flags, timeout_sec,
            ((flags & AUTH_USE_DES) ? accesskeys : (void *)(&accesskey))));
}

Generated by  Doxygen 1.6.0   Back to index