⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 auth.c

📁 一个使用des加密传输的unix下的login程序的服务器端和客户端
💻 C
字号:
/* * @(#) auth.c  RCS: $Revision: 1.4 $ $Date: 95/03/02 12:53:56 $ * * This file contains all the routines needed to interface to routines to  * perform digital signatures, and stream data encryption.  Currently it  * uses the des.  If another method is used, this module should be the only * one changed. */#define _POSIX_SOURCE#include <sys/types.h>	/* pid_t */#include <unistd.h>	/* write getpid */#include <stdio.h>#include <string.h>	/* memset memcmp */#include <ctype.h>	/* isspace */#include <stdlib.h>	/* exit free (after ctype.h for BSDI BSD/386) */#include <time.h>#include "auth.h"#include "txfr.h"#include "log.h"#include "deslogin.h"extern int verbose;typedef struct {   char     iv[DES_BLOCKSIZE];   unsigned ivlen;   keyType  key;   int 	    mode;} cipherState;cipherKey mkCipherKey(key, mode)   keyType key;   int mode;{   cipherState *cs =(cipherState *)malloc(sizeof (cipherState));   if (cs != (cipherState *) 0) {      memset(cs->iv, '\0', DES_BLOCKSIZE);      cs->ivlen = DES_BLOCKSIZE;      cs->key   = key;      cs->mode  = mode;   }   return (cipherKey) cs;}void destroyCipherKey(c)   cipherKey *c;{   register cipherState *cs = * (cipherState **) c;   if (cs != (cipherState *) 0) {      memset(cs->iv, '\0', DES_BLOCKSIZE);      cs->ivlen = 0;      cs->key   = (keyType) 0;      cs->mode  = 0;      free(cs);      *c = (cipherKey) 0;   }}void cipherData(dst, src, size, c)   char *dst, *src;   unsigned size;   cipherKey c;{   register cipherState *cs = (cipherState *) c;   if (cs->key != (keyType) 0) {      cs->ivlen = desCFB(dst, src, size, cs->iv, cs->ivlen, cs->key, cs->mode);   } else {      memcpy(dst, src, size);   }}/* * Convert a string of bytes to their hex representation */char *hexData(dst, src, size)   register char *dst, *src;   register unsigned size;{   register char *chp = dst;   if (size != 0) do {      sprintf(chp, "%.2x", * (unsigned char *) src++);      chp += 2;   } while (--size != 0);   return dst;}/* * Create a key from a keyString * * Mode: 0 = encrypt, 1 = decrypt */keyType mkKey(keyString) 		   char *keyString;{   char 	keybits[DES_BLOCKSIZE];   keyType key = (keyType) 0;   desKey(keybits, keyString, ' ');		/* hash string into 64-bits */   desMakeKey(&key, keybits, DES_BLOCKSIZE, 0);	/* always encrypt for CFB */   memset(keybits, '\0', DES_BLOCKSIZE);   return key;}/* * Perform one DES encryption(decryption if mode nonzero) (ECB mode) * * Dst and src must be exactly DES_BLOCKSIZE bytes long. */void cipherKeyString(dst, src, keyString, mode)   char *dst, *src, *keyString;   int mode;			/* 0 = encipher, 1 = decipher */{   char 	keybits[DES_BLOCKSIZE];   keyType key = (keyType) 0;   desKey(keybits, keyString, ' ');		/* hash string into 64-bits */   desMakeKey(&key, keybits, DES_BLOCKSIZE, mode);   memset(keybits, '\0', DES_BLOCKSIZE);   des(dst, src, key);   desDestroyKey(&key);}/* * Generate a unique session key from the challenge.  The idea here is to allow * the program on both the client and server side to destroy the user's  * private key from memory ASAP.  If a user on the local machine tries to * scan the process memory, they can only compromise the session key and not * the user's long-term login key. */keyType sessionKey(challenge, keyString, mode)   char *challenge, *keyString;   int mode;{   char    keybits[DES_BLOCKSIZE];   keyType res = (keyType) 0;   cipherKeyString(keybits, challenge, keyString, 0);		/* encrypt */   desMakeKey(&res, keybits, DES_BLOCKSIZE, mode);   memset(keybits, '\0', DES_BLOCKSIZE);   return res;}/** Issue and validate a crypto challenge * * Returns: session key if success, 0 if failure */keyType challenge(fd, keyString, timeout)   int fd;   char *keyString;   unsigned timeout;{   char plainText[DES_BLOCKSIZE], cipherText[DES_BLOCKSIZE];   char buf[DES_BLOCKSIZE], buf2[DES_BLOCKSIZE*2+1];   int wcount, rcount, res;   keyType result = (keyType) 0;   /*    * The challenge message must be unpredictable and ideally, never reused    * to prevent playback, or anticipating the next challenge response    *    * To make it unpredictable, take the current time + current pid , and     * encipher it once with the user's key.  This is then used as the     * plaintext of the challenge.      */   memset(cipherText, '\0', DES_BLOCKSIZE);   time((time_t *) &cipherText[0]);   * (unsigned *) &cipherText[4] = (unsigned) getpid();   cipherKeyString(plainText, cipherText, keyString, 0);   cipherKeyString(cipherText, plainText, keyString, 0);	/* encrypt */   if (debug) {      log("%s: challenge(%s)\n", 	  progName, hexData(buf2, cipherText, DES_BLOCKSIZE));   }   wcount = write(fd, cipherText, DES_BLOCKSIZE);   if (wcount != DES_BLOCKSIZE) {      log("%s: challenge--write failed; %s\n", progName, ERRMSG);      exit(1);   }   cipherKeyString(buf, cipherText, keyString, 1);	/* decrypt */   rcount = getBlock(fd, buf, DES_BLOCKSIZE, timeout);	/* decrypt */   if (debug) {      if (rcount > 0) {	 log("%s: response(%s)\n", progName, hexData(buf2, buf, DES_BLOCKSIZE));      }   }   /*    * The remote user deciphers the challenge and it'd better be the same    * as the one we originally enciphered to be a valid signature    */   if (rcount == DES_BLOCKSIZE) {      res = memcmp(buf, plainText, DES_BLOCKSIZE);      if (res == 0) {	 result = sessionKey(cipherText, keyString, 0);      }   }   return result;}/* * Wait for and respond to a crypto challenge return the session key. */keyType signature(fd, keyString, timeout)   int fd;   char *keyString;   unsigned timeout;{   keyType res = (keyType) 0;   char plainText[DES_BLOCKSIZE], cipherText[DES_BLOCKSIZE];   register int wcount = -1, rcount;   rcount = getBlock(fd, cipherText, DES_BLOCKSIZE, timeout);   if (rcount == DES_BLOCKSIZE) {      cipherKeyString(plainText, cipherText, keyString, 1);	/* decrypt */      wcount = write(fd, plainText, rcount);      res = sessionKey(cipherText, keyString, 0);   }   return res;}/* * Find the corresponding passphrase for the given user name. * * The user file is a sequence of lines with username passphrase pairs * Lines beginning with '#' are comments, empty lines are permitted. * * Returns: -2 if key incorrect, -1 if open failed, 0 no such user, 1 success */int getUserPhrase(fname, phrase, size, uname, key)   char *fname;   register char *phrase;   register unsigned size;   char *uname;   keyType key;{   register int i;   char cipherChar, ch;   register int res = -2, state = 0;   register char *chp = 0;   FILE *f = fopen(fname, "r");   cipherKey ck = (cipherKey) 0;   ck = mkCipherKey(key, 1);		/* decrypt */   if (f == NULL) return -1;   do {      i = getc(f);      if (i == EOF)  {	 res = 0; 	 break;      }      cipherChar = (char) i;      cipherData(&ch, &cipherChar, 1, ck);      if (ch & 0x80) break;		/* non-printable character: stop! */      switch (state) {      case 0:					 if (ch == '#') { 	    state = 1;	    break;	 } 	 chp = uname;	 state = 2;			/* fall through */      case 2:				/* user field leading whitespace */	 if (ch == '\n') state = 0;	 if (ch == '#') {	    state = 1;	    break;	 }	 if (isspace(ch)) break;	/* newline is also whitespace */	 state = 3;			/* fall through */      case 3:				/* user field */	 if (!isspace(ch)) {	    if (*chp++ != ch) state = 1;	 } else {	    if (*chp == '\0') {		/* match? */	       if (ch == '\n') state = 6; else state = 4;	       if (verbose) log("founduser\n");	    } else {	       state = 0;	    }	 }	 break;      case 1:				/* skip remainder of line */	 if (ch == '\n') state = 0;	 break;      case 4:				/* passphrase leading whitespace */	 if (ch == '\n') state = 6;	 if (isspace(ch)) break;	 state = 5;			/* fall through */	 chp = phrase;      case 5:				/* passphrase */	 if (ch == '\n') {	    if (size != 0) *chp = '\0';	    state = 6;	    res   = 1;	 }  else {	    if (size != 0) {	       *chp++ = ch;	       --size;	    }	 }	 break;      }   } while (state != 6);   destroyCipherKey(&ck);   fclose(f);   return res;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -