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

📄 prandom.c

📁 DHCP服务器源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef LINTstatic const char rcsid[] = "$Header: /proj/cvs/prod/DHCP/dst/prandom.c,v 1.1 2001/02/22 07:22:09 mellon Exp $";#endif/* * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc. * * Permission to use, copy modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THE SOFTWARE. */#include <stdio.h>#include <sys/types.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <time.h>#include <dirent.h>#include <sys/param.h>#include <sys/stat.h>#include <sys/time.h>#include <netinet/in.h>#include <sys/socket.h>#define NEED_PRAND_CONF#include "minires/minires.h"#include "dst_internal.h"#include "arpa/nameser.h"#ifndef DST_NUM_HASHES#define DST_NUM_HASHES 4#endif#ifndef DST_NUMBER_OF_COUNTERS#define DST_NUMBER_OF_COUNTERS 5	/* 32 * 5 == 160 == SHA(1) > MD5 */#endif/*  * the constant below is a prime number to make fixed data structues like  * stat and time wrap over blocks. This adds certain uncertanty to what is  * in each digested block.  * The prime number 2879 has the special property that when  * divided by 2,4 and 6 the result is also a prime numbers */#ifndef DST_RANDOM_BLOCK_SIZE#define DST_RANDOM_BLOCK_SIZE 2879#endif/*  * This constant dictatates how many bits we shift to the right before using a  */#ifndef DST_SHIFT#define DST_SHIFT 9#endif/* * An initalizer that is as bad as any other with half the bits set  */#ifndef DST_RANDOM_PATTERN#define DST_RANDOM_PATTERN 0x8765CA93#endif/*  * things must have changed in the last 3600 seconds to be used  */#define MAX_OLD 3600/*   *  these two data structure are used to process input data into digests,  * *  The first structure is containts a pointer to a DST HMAC key  *  the variables accompanying are used for  *	step : select every step byte from input data for the hash *	block: number of data elements going into each hash *	digested: number of data elements digested so far *	curr: offset into the next input data for the first byte.  */typedef struct hash {	DST_KEY *key;	void *ctx;	int digested, block, step, curr;} prand_hash;/* *  This data structure controlls number of hashes and keeps track of  *  overall progress in generating correct number of bytes of output. *	output  : array to store the output data in *	needed  : how many bytes of output are needed *	filled  : number of bytes in output so far.  *	bytes   : total number of bytes processed by this structure *	file_digest : the HMAC key used to digest files. */typedef struct work {	unsigned needed, filled, bytes;	u_char *output;	prand_hash *hash[DST_NUM_HASHES];	DST_KEY *file_digest;} dst_work;/*  * forward function declarations  */static int get_dev_random(u_char *output, unsigned size);static int do_time(dst_work *work);static int do_ls(dst_work *work);static int unix_cmd(dst_work *work);static int digest_file(dst_work *work);static void force_hash(dst_work *work, prand_hash *hash);static int do_hash(dst_work *work, prand_hash *hash, const u_char *input,		   unsigned size);static int my_digest(dst_work *tmp, const u_char *input, unsigned size);static prand_hash *get_hmac_key(int step, int block);static unsigned own_random(dst_work *work);/*  * variables used in the quick random number generator  */static u_int32_t ran_val = DST_RANDOM_PATTERN;static u_int32_t ran_cnt = (DST_RANDOM_PATTERN >> 10);/*  * setting the quick_random generator to particular values or if both  * input parameters are 0 then set it to initial vlaues */voiddst_s_quick_random_set(u_int32_t val, u_int32_t cnt){	ran_val = (val == 0) ? DST_RANDOM_PATTERN : val;	ran_cnt = (cnt == 0) ? (DST_RANDOM_PATTERN >> 10) : cnt;}/*  * this is a quick and random number generator that seems to generate quite  * good distribution of data  */u_int32_tdst_s_quick_random(int inc){	ran_val = ((ran_val >> 13) ^ (ran_val << 19)) ^		((ran_val >> 7) ^ (ran_val << 25));	if (inc > 0)		/* only increasing values accepted */		ran_cnt += inc;	ran_val += ran_cnt++;	return (ran_val);}/*  * get_dev_random: Function to read /dev/random reliably * this function returns how many bytes where read from the device. * port_after.h should set the control variable HAVE_DEV_RANDOM  */static intget_dev_random(u_char *output, unsigned size){#ifdef HAVE_DEV_RANDOM	struct stat st;	int n = 0, fd = -1, s;	s = stat("/dev/random", &st);	if (s == 0 && S_ISCHR(st.st_mode)) {		if ((fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) != -1) {			if ((n = read(fd, output, size)) < 0)				n = 0;			close(fd);		}		return (n);	}#endif	return (0);}/* * Portable way of getting the time values if gettimeofday is missing  * then compile with -DMISSING_GETTIMEOFDAY  time() is POSIX compliant but * gettimeofday() is not. * Time of day is predictable, we are looking for the randomness that comes  * the last few bits in the microseconds in the timer are hard to predict when  * this is invoked at the end of other operations */struct timeval *mtime;static intdo_time(dst_work *work){	int cnt = 0;	static u_char tmp[sizeof(struct timeval) + sizeof(struct timezone)];	struct timezone *zone;	zone = (struct timezone *) tmp;	mtime = (struct timeval *)(tmp + sizeof(struct timezone));	gettimeofday(mtime, zone);	cnt = sizeof(tmp);	my_digest(work, tmp, sizeof(tmp));	return (cnt);}/* * this function simulates the ls command, but it uses stat which gives more * information and is harder to guess  * Each call to this function will visit the next directory on the list of  * directories, in a circular manner.  * return value is the number of bytes added to the temp buffer * * do_ls() does not visit subdirectories * if attacker has access to machine it can guess most of the values seen * thus it is important to only visit directories that are freqently updated * Attacker that has access to the network can see network traffic  * when NFS mounted directories are accessed and know exactly the data used * but may not know exactly in what order data is used.  * Returns the number of bytes that where returned in stat structures */static intdo_ls(dst_work *work){	struct dir_info { 		uid_t  uid;		gid_t  gid;		off_t size;		time_t atime, mtime, ctime;	};	static struct dir_info dir_info;	struct stat buf;	struct dirent *entry;	static int i = 0;	static unsigned long d_round = 0;	struct timeval tv;	int n = 0, tb_i = 0, out = 0;	unsigned dir_len;	char file_name[1024];	u_char tmp_buff[1024]; 	DIR *dir = NULL;	if (dirs[i] == NULL) 	/* if at the end of the list start over */		i = 0;	if (stat(dirs[i++], &buf))  /* directory does not exist */		return (0);	gettimeofday(&tv,NULL);	if (d_round == 0) 		d_round = tv.tv_sec - MAX_OLD;	else if (i==1) /* if starting a new round cut what we accept */		d_round += (tv.tv_sec - d_round)/2;	if (buf.st_atime < d_round) 		return (0);	EREPORT(("do_ls i %d filled %4d in_temp %4d\n",		 i-1, work->filled, work->in_temp));	memcpy(tmp_buff, &buf, sizeof(buf)); 	tb_i += sizeof(buf);	if ((dir = opendir(dirs[i-1])) == NULL)/* open it for read */		return (0);	strcpy(file_name, dirs[i-1]);	dir_len = strlen(file_name);	file_name[dir_len++] = '/';	while ((entry = readdir(dir))) {		unsigned len = strlen(entry->d_name);		out += len;		if (my_digest(work, (u_char *)entry->d_name, len))			break;			memcpy(&file_name[dir_len], entry->d_name, len);		file_name[dir_len + len] = 0x0;		/* for all entries in dir get the stats */		if (stat(file_name, &buf) == 0) {			n++;	/* count successfull stat calls */			/* copy non static fields */			dir_info.uid   += buf.st_uid;			dir_info.gid   += buf.st_gid;			dir_info.size  += buf.st_size;			dir_info.atime += buf.st_atime;			dir_info.mtime += buf.st_mtime;			dir_info.ctime += buf.st_ctime;			out += sizeof(dir_info);			if(my_digest(work, (u_char *)&dir_info, 				     sizeof(dir_info)))				break; 		}	}	closedir(dir);	/* done */	out += do_time(work);	/* add a time stamp */	return (out);}/*  * unix_cmd()  * this function executes the a command from the cmds[] list of unix commands  * configured in the prand_conf.h file * return value is the number of bytes added to the randomness temp buffer *  * it returns the number of bytes that where read in * if more data is needed at the end time is added to the data. * This function maintains a state to selects the next command to run * returns the number of bytes read in from the command  */static intunix_cmd(dst_work *work){	static int cmd_index = 0;	int cnt = 0, n;	FILE *pipe;	u_char buffer[4096];	if (cmds[cmd_index] == NULL)		cmd_index = 0;	EREPORT(("unix_cmd() i %d filled %4d in_temp %4d\n",		 cmd_index, work->filled, work->in_temp));	pipe = popen(cmds[cmd_index++], "r");	/* execute the command */	while ((n = fread(buffer, sizeof(char), sizeof(buffer), pipe)) > 0) {		cnt += n;	/* process the output */		if (my_digest(work, buffer, (unsigned)n))			break;		/* this adds some randomness to the output */		cnt += do_time(work);	}	while ((n = fread(buffer, sizeof(char), sizeof(buffer), pipe)) > 0)		NULL; /* drain the pipe */	pclose(pipe);	return (cnt);		/* read how many bytes where read in */}/*  * digest_file() This function will read a file and run hash over it * input is a file name  */ static int digest_file(dst_work *work) {	static int f_cnt = 0;	static unsigned long f_round = 0;	FILE *fp; 	void *ctx;	const char *name;	int no, i; 	struct stat st;	struct timeval tv;	u_char buf[1024];	if (f_round == 0 || files[f_cnt] == NULL || work->file_digest == NULL) 		if (gettimeofday(&tv, NULL)) /* only do this if needed */			return (0);	if (f_round == 0)   /* first time called set to one hour ago */		f_round = (tv.tv_sec - MAX_OLD); 	name = files[f_cnt++]; 	if (files[f_cnt] == NULL) {  /* end of list of files */		if(f_cnt <= 1)       /* list is too short */			return (0);		f_cnt = 0;           /* start again on list */		f_round += (tv.tv_sec - f_round)/2; /* set new cutoff */		work->file_digest = dst_free_key(work->file_digest);	}	if (work->file_digest == NULL) {		work->file_digest  = dst_buffer_to_key("", KEY_HMAC_MD5, 0, 0, 					    (u_char *)&tv, sizeof(tv));		if (work->file_digest == NULL)			return (0);	}	if (access(name, R_OK) || stat(name, &st))		return (0); /* no such file or not allowed to read it */	if (strncmp(name, "/proc/", 6) && st.st_mtime < f_round)  		return(0); /* file has not changed recently enough */	if (dst_sign_data(SIG_MODE_INIT, work->file_digest, &ctx, 			  NULL, 0, NULL, 0)) {		work->file_digest = dst_free_key(work->file_digest);		return (0);	}	if ((fp = fopen(name, "r")) == NULL) 		return (0);	for (no = 0; (i = fread(buf, sizeof(*buf), sizeof(buf), fp)) > 0; 	     no += i) 		dst_sign_data(SIG_MODE_UPDATE, work->file_digest, &ctx, 			      buf, (unsigned)i, NULL, 0);	fclose(fp);	if (no >= 64) {		i = dst_sign_data(SIG_MODE_FINAL, work->file_digest, &ctx, 				  NULL, 0, &work->output[work->filled], 				  DST_HASH_SIZE);	  		if (i > 0) 			work->filled += i;	}	else if (i > 0)		my_digest(work, buf, (unsigned)i);	my_digest(work, (const u_char *)name, strlen(name));	return (no + strlen(name));}/*  * function to perform the FINAL and INIT operation on a hash if allowed */static voidforce_hash(dst_work *work, prand_hash *hash){	int i = 0;	/* 	 * if more than half a block then add data to output 	 * otherwise adde the digest to the next hash 	 */	if ((hash->digested * 2) > hash->block) {		i = dst_sign_data(SIG_MODE_FINAL, hash->key, &hash->ctx,				  NULL, 0, &work->output[work->filled],				  DST_HASH_SIZE);		hash->digested = 0;		dst_sign_data(SIG_MODE_INIT, hash->key, &hash->ctx, 			      NULL, 0, NULL, 0);		if (i > 0)			work->filled += i;	}	return;

⌨️ 快捷键说明

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