File: | lib/nettle/egd.c |
Location: | line 206, column 3 |
Description: | Value stored to 'do_restart' is never read |
1 | /* rndegd.c - interface to the EGD |
2 | * Copyright (C) 1999-2000, 2002-2003, 2010, 2012 Free Software |
3 | * Foundation, Inc. |
4 | * |
5 | * This file is part of Libgcrypt. |
6 | * |
7 | * Libgcrypt is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU Lesser General Public License as |
9 | * published by the Free Software Foundation; either version 3 of |
10 | * the License, or (at your option) any later version. |
11 | * |
12 | * Libgcrypt is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public License |
18 | * along with this program. If not, see <http://www.gnu.org/licenses/> |
19 | * |
20 | */ |
21 | |
22 | #include <config.h> |
23 | |
24 | #ifndef _WIN32 |
25 | |
26 | #include <stdio.h> |
27 | #include <stdlib.h> |
28 | #include <errno(*__errno_location ()).h> |
29 | #include <sys/time.h> |
30 | #include <sys/stat.h> |
31 | #include <string.h> |
32 | #include <unistd.h> |
33 | #include <sys/types.h> |
34 | #include <sys/socket.h> |
35 | #include <sys/un.h> |
36 | #include "egd.h" |
37 | #include <gnutls_int.h> |
38 | #include <gnutls_str.h> |
39 | #include <gnutls_errors.h> |
40 | |
41 | #ifdef AF_UNIX1 |
42 | # define LOCAL_SOCKET_TYPE1 AF_UNIX1 |
43 | #else |
44 | # define LOCAL_SOCKET_TYPE1 AF_LOCAL1 |
45 | #endif |
46 | |
47 | #ifndef offsetof |
48 | #define offsetof(type, member)__builtin_offsetof(type, member) ((size_t) &((type *)0)->member) |
49 | #endif |
50 | |
51 | static int egd_socket = -1; |
52 | |
53 | static int |
54 | do_write (int fd, void *buf, size_t nbytes) |
55 | { |
56 | size_t nleft = nbytes; |
57 | int nwritten; |
58 | |
59 | while (nleft > 0) |
60 | { |
61 | nwritten = write (fd, buf, nleft); |
62 | if (nwritten < 0) |
63 | { |
64 | if (errno(*__errno_location ()) == EINTR4) |
65 | continue; |
66 | return -1; |
67 | } |
68 | nleft -= nwritten; |
69 | buf = (char *) buf + nwritten; |
70 | } |
71 | return 0; |
72 | } |
73 | |
74 | static int |
75 | do_read (int fd, void *buf, size_t nbytes) |
76 | { |
77 | int n, nread = 0; |
78 | |
79 | do |
80 | { |
81 | do |
82 | { |
83 | n = read (fd, (char *) buf + nread, nbytes); |
84 | } |
85 | while (n == -1 && errno(*__errno_location ()) == EINTR4); |
86 | if (n == -1) |
87 | return nread ? nread : -1; |
88 | if (n == 0) |
89 | return -1; |
90 | nread += n; |
91 | nbytes -= n; |
92 | } |
93 | while (nread < nbytes); |
94 | return nread; |
95 | } |
96 | |
97 | static const char *egd_names[] = { |
98 | "/var/run/egd-pool", |
99 | "/dev/egd-pool", |
100 | "/etc/egd-pool", |
101 | "/etc/entropy", |
102 | "/var/run/entropy", |
103 | "/dev/entropy", |
104 | NULL((void*)0) |
105 | }; |
106 | |
107 | static const char * |
108 | find_egd_name (void) |
109 | { |
110 | int i = 0; |
111 | struct stat st; |
112 | |
113 | do |
114 | { |
115 | if (stat (egd_names[i], &st) != 0) |
116 | continue; |
117 | |
118 | if (st.st_mode & S_IFSOCK0140000) |
119 | { /* found */ |
120 | return egd_names[i]; |
121 | } |
122 | |
123 | } |
124 | while (egd_names[++i] != NULL((void*)0)); |
125 | |
126 | return NULL((void*)0); |
127 | } |
128 | |
129 | /* Connect to the EGD and return the file descriptor. Return -1 on |
130 | error. With NOFAIL set to true, silently fail and return the |
131 | error, otherwise print an error message and die. */ |
132 | int |
133 | _rndegd_connect_socket (void) |
134 | { |
135 | int fd; |
136 | const char *name; |
137 | struct sockaddr_un addr; |
138 | int addr_len; |
139 | |
140 | if (egd_socket != -1) |
141 | { |
142 | close (egd_socket); |
143 | egd_socket = -1; |
144 | } |
145 | |
146 | name = find_egd_name (); |
147 | |
148 | if (strlen (name) + 1 >= sizeof addr.sun_path) |
149 | { |
150 | _gnutls_debug_log ("EGD socketname is too long\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "EGD socketname is too long\n"); } while(0); |
151 | return -1; |
152 | } |
153 | |
154 | memset (&addr, 0, sizeof addr); |
155 | addr.sun_family = LOCAL_SOCKET_TYPE1; |
156 | _gnutls_str_cpy (addr.sun_path, sizeof(addr.sun_path), name); |
157 | addr_len = (offsetof (struct sockaddr_un, sun_path)__builtin_offsetof(struct sockaddr_un, sun_path) |
158 | + strlen (addr.sun_path)); |
159 | |
160 | fd = socket (LOCAL_SOCKET_TYPE1, SOCK_STREAMSOCK_STREAM, 0); |
161 | if (fd == -1) |
162 | { |
163 | _gnutls_debug_log ("can't create unix domain socket: %s\n",do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "can't create unix domain socket: %s\n", rpl_strerror (( *__errno_location ()))); } while(0) |
164 | strerror (errno))do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "can't create unix domain socket: %s\n", rpl_strerror (( *__errno_location ()))); } while(0); |
165 | return -1; |
166 | } |
167 | else if (connect (fd, (struct sockaddr *) &addr, addr_len) == -1) |
168 | { |
169 | _gnutls_debug_log ("can't connect to EGD socket `%s': %s\n",do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "can't connect to EGD socket `%s': %s\n", name, rpl_strerror ((*__errno_location ()))); } while(0) |
170 | name, strerror (errno))do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "can't connect to EGD socket `%s': %s\n", name, rpl_strerror ((*__errno_location ()))); } while(0); |
171 | close (fd); |
172 | fd = -1; |
173 | } |
174 | |
175 | if (fd != -1) |
176 | egd_socket = fd; |
177 | return fd; |
178 | } |
179 | |
180 | /**************** |
181 | * Note: We always use the highest level. |
182 | * To boost the performance we may want to add some |
183 | * additional code for level 1 |
184 | * |
185 | * Using a level of 0 should never block and better add nothing |
186 | * to the pool. So this is just a dummy for EGD. |
187 | */ |
188 | int |
189 | _rndegd_read (int *fd, void *_output, size_t _length) |
190 | { |
191 | int n; |
192 | uint8_t buffer[256 + 2]; |
193 | int nbytes; |
194 | int do_restart = 0; |
195 | unsigned char *output = _output; |
196 | size_t length = _length; |
197 | |
198 | if (!length) |
199 | return 0; |
200 | |
201 | |
202 | restart: |
203 | if (*fd == -1 || do_restart) |
204 | *fd = _rndegd_connect_socket (); |
205 | |
206 | do_restart = 0; |
Value stored to 'do_restart' is never read | |
207 | |
208 | nbytes = length < 255 ? length : 255; |
209 | /* First time we do it with a non blocking request */ |
210 | buffer[0] = 1; /* non blocking */ |
211 | buffer[1] = nbytes; |
212 | |
213 | if (do_write (*fd, buffer, 2) == -1) |
214 | _gnutls_debug_log ("can't write to the EGD: %s\n", strerror (errno))do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "can't write to the EGD: %s\n", rpl_strerror ((*__errno_location ()))); } while(0); |
215 | |
216 | n = do_read (*fd, buffer, 1); |
217 | if (n == -1) |
218 | { |
219 | _gnutls_debug_log ("read error on EGD: %s\n", strerror (errno))do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "read error on EGD: %s\n", rpl_strerror ((*__errno_location ()))); } while(0); |
220 | do_restart = 1; |
221 | goto restart; |
222 | } |
223 | |
224 | n = buffer[0]; |
225 | if (n) |
226 | { |
227 | n = do_read (*fd, buffer, n); |
228 | if (n == -1) |
229 | { |
230 | _gnutls_debug_log ("read error on EGD: %s\n", strerror (errno))do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "read error on EGD: %s\n", rpl_strerror ((*__errno_location ()))); } while(0); |
231 | do_restart = 1; |
232 | goto restart; |
233 | } |
234 | |
235 | if (n > length) |
236 | { |
237 | _gnutls_debug_log ("read error on EGD: returned more bytes!\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "read error on EGD: returned more bytes!\n"); } while(0); |
238 | n = length; |
239 | } |
240 | |
241 | memcpy (output, buffer, n); |
242 | output += n; |
243 | length -= n; |
244 | } |
245 | |
246 | while (length) |
247 | { |
248 | nbytes = length < 255 ? length : 255; |
249 | |
250 | buffer[0] = 2; /* blocking */ |
251 | buffer[1] = nbytes; |
252 | if (do_write (*fd, buffer, 2) == -1) |
253 | _gnutls_debug_log ("can't write to the EGD: %s\n", strerror (errno))do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "can't write to the EGD: %s\n", rpl_strerror ((*__errno_location ()))); } while(0); |
254 | n = do_read (*fd, buffer, nbytes); |
255 | if (n == -1) |
256 | { |
257 | _gnutls_debug_log ("read error on EGD: %s\n", strerror (errno))do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "read error on EGD: %s\n", rpl_strerror ((*__errno_location ()))); } while(0); |
258 | do_restart = 1; |
259 | goto restart; |
260 | } |
261 | |
262 | if (n > length) |
263 | { |
264 | _gnutls_debug_log ("read error on EGD: returned more bytes!\n")do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "read error on EGD: returned more bytes!\n"); } while(0); |
265 | n = length; |
266 | } |
267 | |
268 | memcpy (output, buffer, n); |
269 | output += n; |
270 | length -= n; |
271 | } |
272 | |
273 | return _length; /* success */ |
274 | } |
275 | |
276 | #endif |