OpenVAS Libraries  9.0.3
genrand.c
Go to the documentation of this file.
1 /*
2  Unix SMB/CIFS implementation.
3 
4  Functions to create reasonable random numbers for crypto use.
5 
6  Copyright (C) Jeremy Allison 2001
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22 
23 /*
24  Modified for OpenVAS by Preeti Subramanian <spreeti@secpod.com>
25  MODIFICATION: This file has only those functions that cater to the
26  requirements of OpenVAS, remaining functions are removed
27  * BOOL is changed to bool
28  * sys_open is changed to open
29  * sys_getpid is changed to getpid
30  * In do_reseed function, adding secret file contents of smb
31  passwd file not required(removed) and add in the root encrypted
32  password note required(removed)
33 */
34 #include <pwd.h>
35 #include <unistd.h>
36 #include "byteorder.h"
37 #include "smb.h"
38 #include <time.h>
39 #include "md4.h"
40 #include "proto.h"
41 #ifndef HAVE_UCBINCLUDE
42 #include <fcntl.h>
43 #else
44 /* Solaris */
45 #include "/usr/ucbinclude/fcntl.h"
46 #endif
47 
48 #ifndef uint32
49 #define uint32 uint32_t
50 #endif
51 
52 typedef unsigned int bool;
53 #define False 0
54 #define True 1
55 
56 static unsigned char smb_arc4_state[258];
57 static uint32 counter;
58 
64 /* zero a structure */
65 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
66 
67 static bool done_reseed_ntlmssp = False;
68 static void (*reseed_callback_ntlmssp)(int *newseed);
69 
70 /****************************************************************
71  Copy any user given reseed data.
72 *****************************************************************/
73 
74 static void get_rand_reseed_data_ntlmssp(int *reseed_data)
75 {
76  if (reseed_callback_ntlmssp) {
77  reseed_callback_ntlmssp(reseed_data);
78  } else {
79  *reseed_data = 0;
80  }
81 }
82 
83 /****************************************************************
84  Get a 16 byte hash from the contents of a file.
85  Note that the hash is not initialised.
86 *****************************************************************/
87 
88 static void do_filehash_ntlmssp(const char *fname, unsigned char *the_hash)
89 {
90  unsigned char buf[1011]; /* deliberate weird size */
91  unsigned char tmp_md4[16];
92  int fd, n;
93 
94  fd = open(fname,O_RDONLY,0);
95  if (fd == -1)
96  return;
97 
98  while ((n = read(fd, (char *)buf, sizeof(buf))) > 0) {
99  mdfour_ntlmssp(tmp_md4, buf, n);
100  for (n=0;n<16;n++)
101  the_hash[n] ^= tmp_md4[n];
102  }
103  close(fd);
104 }
105 
106 /**************************************************************
107  Try and get a good random number seed. Try a number of
108  different factors. Firstly, try /dev/urandom - use if exists.
109 
110  We use /dev/urandom as a read of /dev/random can block if
111  the entropy pool dries up. This leads clients to timeout
112  or be very slow on connect.
113 
114  If we can't use /dev/urandom then seed the stream random generator
115  above...
116 **************************************************************/
117 
118 static int do_reseed_ntlmssp(bool use_fd, int fd)
119 {
120  unsigned char seed_inbuf[40];
121  uint32 v1, v2; struct timeval tval; pid_t mypid;
122  int reseed_data = 0;
123 
124  if (use_fd) {
125  if (fd != -1)
126  return fd;
127  fd = open( "/dev/urandom", O_RDONLY,0);
128  if(fd >= 0)
129  return fd;
130  }
131 
132  /* Add in some secret file contents */
133 
134  do_filehash_ntlmssp("/etc/shadow", &seed_inbuf[0]);
135  /*
136  * Add the counter, time of day, and pid.
137  */
138 
139  GetTimeOfDay_ntlmssp(&tval);
140  mypid = getpid();
141  v1 = (counter++) + mypid + tval.tv_sec;
142  v2 = (counter++) * mypid + tval.tv_usec;
143 
144  SIVAL(seed_inbuf, 32, v1 ^ IVAL(seed_inbuf, 32));
145  SIVAL(seed_inbuf, 36, v2 ^ IVAL(seed_inbuf, 36));
146 
147  /*
148  * Add any user-given reseed data.
149  */
150 
151  get_rand_reseed_data_ntlmssp(&reseed_data);
152  if (reseed_data) {
153  size_t i;
154  for (i = 0; i < sizeof(seed_inbuf); i++)
155  seed_inbuf[i] ^= ((char *)(&reseed_data))[i % sizeof(reseed_data)];
156  }
157 
158  smb_arc4_init_ntlmssp(smb_arc4_state, seed_inbuf, sizeof(seed_inbuf));
159 
160  return -1;
161 }
162 
163 /*******************************************************************
164  Interface to the (hopefully) good crypto random number generator.
165 ********************************************************************/
166 
167 void generate_random_buffer_ntlmssp( unsigned char *out, int len)
168 {
169  static int urand_fd = -1;
170  unsigned char md4_buf[64];
171  unsigned char tmp_buf[16];
172  unsigned char *p;
173 
174  if(!done_reseed_ntlmssp) {
175  urand_fd = do_reseed_ntlmssp(True, urand_fd);
176  done_reseed_ntlmssp = True;
177  }
178 
179  if (urand_fd != -1 && len > 0) {
180 
181  if (read(urand_fd, out, len) == len)
182  return; /* len bytes of random data read from urandom. */
183 
184  /* Read of urand error, drop back to non urand method. */
185  close(urand_fd);
186  urand_fd = -1;
187  do_reseed_ntlmssp(False, -1);
188  done_reseed_ntlmssp = True;
189  }
190 
191  /*
192  * Generate random numbers in chunks of 64 bytes,
193  * then md4 them & copy to the output buffer.
194  * This way the raw state of the stream is never externally
195  * seen.
196  */
197 
198  p = out;
199  while(len > 0) {
200  int copy_len = len > 16 ? 16 : len;
201 
202  smb_arc4_crypt_ntlmssp(smb_arc4_state, md4_buf, sizeof(md4_buf));
203  mdfour_ntlmssp(tmp_buf, md4_buf, sizeof(md4_buf));
204  memcpy(p, tmp_buf, copy_len);
205  p += copy_len;
206  len -= copy_len;
207  }
208 }
#define uint32
Definition: genrand.c:49
unsigned int bool
Definition: genrand.c:52
void GetTimeOfDay_ntlmssp(struct timeval *tval)
Definition: time.c:92
#define True
Definition: genrand.c:54
#define SIVAL(buf, pos, val)
Definition: byteorder.h:123
void mdfour_ntlmssp(unsigned char *out, const unsigned char *in, int n)
Definition: md4.c:125
void generate_random_buffer_ntlmssp(unsigned char *out, int len)
Definition: genrand.c:167
void smb_arc4_crypt_ntlmssp(unsigned char arc4_state_inout[258], unsigned char *data, size_t len)
Definition: arc4.c:57
struct timeval timeval(unsigned long val)
void smb_arc4_init_ntlmssp(unsigned char arc4_state_out[258], const unsigned char *key, size_t keylen)
Definition: arc4.c:30
#define IVAL(buf, pos)
Definition: byteorder.h:117
#define False
Definition: genrand.c:53