]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | ** | |
3 | ** OpenBSD emulation routines | |
4 | ** | |
5 | ** Damien Miller <djm@ibs.com.au> | |
6 | ** | |
7 | ** Copyright 1999 Damien Miller | |
8 | ** Copyright 1999 Internet Business Solutions | |
9 | ** | |
10 | ** Permission is hereby granted, free of charge, to any person | |
11 | ** obtaining a copy of this software and associated documentation | |
12 | ** files (the "Software"), to deal in the Software without | |
13 | ** restriction, including without limitation the rights to use, copy, | |
14 | ** modify, merge, publish, distribute, sublicense, and/or sell copies | |
15 | ** of the Software, and to permit persons to whom the Software is | |
16 | ** furnished to do so, subject to the following conditions: | |
17 | ** | |
18 | ** The above copyright notice and this permission notice shall be | |
19 | ** included in all copies or substantial portions of the Software. | |
20 | ** | |
21 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY | |
22 | ** KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE | |
23 | ** WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE | |
24 | ** AND NONINFRINGEMENT. IN NO EVENT SHALL DAMIEN MILLER OR INTERNET | |
25 | ** BUSINESS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
26 | ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
27 | ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE | |
28 | ** OR OTHER DEALINGS IN THE SOFTWARE. | |
29 | ** | |
30 | ** Except as contained in this notice, the name of Internet Business | |
31 | ** Solutions shall not be used in advertising or otherwise to promote | |
32 | ** the sale, use or other dealings in this Software without prior | |
33 | ** written authorization from Internet Business Solutions. | |
34 | ** | |
35 | */ | |
36 | ||
37 | #include "config.h" | |
38 | ||
39 | #include <stdio.h> | |
40 | #include <stdlib.h> | |
41 | #include <string.h> | |
42 | #include <errno.h> | |
43 | #include <unistd.h> | |
44 | ||
45 | #include <sys/types.h> | |
46 | #include <sys/stat.h> | |
47 | #include <sys/socket.h> | |
48 | #include <sys/un.h> | |
49 | #include <fcntl.h> | |
50 | ||
51 | #include "xmalloc.h" | |
52 | #include "ssh.h" | |
53 | #include "bsd-misc.h" | |
54 | ||
55 | #ifndef offsetof | |
56 | #define offsetof(type, member) ((size_t) &((type *)0)->member) | |
57 | #endif | |
58 | ||
59 | #ifndef HAVE_ARC4RANDOM | |
60 | ||
61 | typedef struct | |
62 | { | |
63 | unsigned int s[256]; | |
64 | int i; | |
65 | int j; | |
66 | } rc4_t; | |
67 | ||
68 | void get_random_bytes(unsigned char *buf, int len); | |
69 | void rc4_key(rc4_t *r, unsigned char *key, int len); | |
70 | void rc4_getbytes(rc4_t *r, unsigned char *buffer, int len); | |
71 | ||
72 | static rc4_t *rc4 = NULL; | |
73 | ||
74 | void rc4_key(rc4_t *r, unsigned char *key, int len) | |
75 | { | |
76 | int t; | |
77 | ||
78 | for(r->i = 0; r->i < 256; r->i++) | |
79 | r->s[r->i] = r->i; | |
80 | ||
81 | r->j = 0; | |
82 | for(r->i = 0; r->i < 256; r->i++) | |
83 | { | |
84 | r->j = (r->j + r->s[r->i] + key[r->i % len]) % 256; | |
85 | t = r->s[r->i]; | |
86 | r->s[r->i] = r->s[r->j]; | |
87 | r->s[r->j] = t; | |
88 | } | |
89 | r->i = r->j = 0; | |
90 | } | |
91 | ||
92 | void rc4_getbytes(rc4_t *r, unsigned char *buffer, int len) | |
93 | { | |
94 | int t; | |
95 | int c; | |
96 | ||
97 | c = 0; | |
98 | while(c < len) | |
99 | { | |
100 | r->i = (r->i + 1) % 256; | |
101 | r->j = (r->j + r->s[r->i]) % 256; | |
102 | t = r->s[r->i]; | |
103 | r->s[r->i] = r->s[r->j]; | |
104 | r->s[r->j] = t; | |
105 | ||
106 | t = (r->s[r->i] + r->s[r->j]) % 256; | |
107 | ||
108 | buffer[c] = r->s[t]; | |
109 | c++; | |
110 | } | |
111 | } | |
112 | ||
113 | unsigned int arc4random(void) | |
114 | { | |
115 | unsigned int r; | |
116 | ||
117 | if (rc4 == NULL) | |
118 | arc4random_stir(); | |
119 | ||
120 | rc4_getbytes(rc4, (unsigned char *)&r, sizeof(r)); | |
121 | ||
122 | return(r); | |
123 | } | |
124 | ||
125 | void arc4random_stir(void) | |
126 | { | |
127 | unsigned char rand_buf[32]; | |
128 | ||
129 | if (rc4 == NULL) | |
130 | rc4 = xmalloc(sizeof(*rc4)); | |
131 | ||
132 | get_random_bytes(rand_buf, sizeof(rand_buf)); | |
133 | rc4_key(rc4, rand_buf, sizeof(rand_buf)); | |
134 | } | |
135 | ||
136 | void get_random_bytes(unsigned char *buf, int len) | |
137 | { | |
138 | static int random_pool; | |
139 | int c; | |
140 | #ifdef HAVE_EGD | |
141 | char egd_message[2] = { 0x02, 0x00 }; | |
142 | struct sockaddr_un addr; | |
143 | int addr_len; | |
144 | ||
145 | memset(&addr, '\0', sizeof(addr)); | |
146 | addr.sun_family = AF_UNIX; | |
147 | ||
148 | /* FIXME: compile time check? */ | |
149 | if (sizeof(RANDOM_POOL) > sizeof(addr.sun_path)) | |
150 | fatal("Random pool path is too long"); | |
151 | ||
152 | strcpy(addr.sun_path, RANDOM_POOL); | |
153 | ||
154 | addr_len = offsetof(struct sockaddr_un, sun_path) + sizeof(RANDOM_POOL); | |
155 | ||
156 | random_pool = socket(AF_UNIX, SOCK_STREAM, 0); | |
157 | ||
158 | if (random_pool == -1) | |
159 | fatal("Couldn't create AF_UNIX socket: %s", strerror(errno)); | |
160 | ||
161 | if (connect(random_pool, (struct sockaddr*)&addr, addr_len) == -1) | |
162 | fatal("Couldn't connect to EGD socket \"%s\": %s", addr.sun_path, strerror(errno)); | |
163 | ||
164 | if (len > 255) | |
165 | fatal("Too many bytes to read from EGD"); | |
166 | ||
167 | /* Send blocking read request to EGD */ | |
168 | egd_message[1] = len; | |
169 | ||
170 | c = atomicio(write, random_pool, egd_message, sizeof(egd_message)); | |
171 | if (c == -1) | |
172 | fatal("Couldn't write to EGD socket \"%s\": %s", RANDOM_POOL, strerror(errno)); | |
173 | ||
174 | #else /* HAVE_EGD */ | |
175 | ||
176 | random_pool = open(RANDOM_POOL, O_RDONLY); | |
177 | if (random_pool == -1) | |
178 | fatal("Couldn't open random pool \"%s\": %s", RANDOM_POOL, strerror(errno)); | |
179 | ||
180 | #endif /* HAVE_EGD */ | |
181 | ||
182 | c = atomicio(read, random_pool, buf, len); | |
183 | if (c <= 0) | |
184 | fatal("Couldn't read from random pool \"%s\": %s", RANDOM_POOL, strerror(errno)); | |
185 | ||
186 | close(random_pool); | |
187 | } | |
188 | #endif /* !HAVE_ARC4RANDOM */ | |
189 | ||
190 | #ifndef HAVE_SETPROCTITLE | |
191 | void setproctitle(const char *fmt, ...) | |
192 | { | |
193 | /* FIXME */ | |
194 | } | |
195 | #endif /* !HAVE_SETPROCTITLE */ | |
196 | ||
197 | #ifndef HAVE_SETENV | |
198 | int setenv(const char *name, const char *value, int overwrite) | |
199 | { | |
200 | char *env_string; | |
201 | int result; | |
202 | ||
203 | /* Don't overwrite existing env. var if overwrite is 0 */ | |
204 | if (!overwrite && (getenv(name) != NULL)) | |
205 | return(0); | |
206 | ||
207 | env_string = xmalloc(strlen(name) + strlen(value) + 2); | |
208 | sprintf(env_string, "%s=%s", name, value); | |
209 | ||
210 | result = putenv(env_string); | |
211 | ||
212 | xfree(env_string); | |
213 | ||
214 | return(result); | |
215 | } | |
216 | #endif /* !HAVE_SETENV */ | |
217 | ||
218 | #ifndef HAVE_SETLOGIN | |
219 | int setlogin(const char *name) | |
220 | { | |
221 | return(0); | |
222 | } | |
223 | #endif /* !HAVE_SETLOGIN */ | |
224 | ||
225 | #ifndef HAVE_INNETGR | |
226 | int innetgr(const char *netgroup, const char *host, | |
227 | const char *user, const char *domain) | |
228 | { | |
229 | return(0); | |
230 | } | |
231 | #endif /* HAVE_INNETGR */ | |
232 | ||
233 | #if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) | |
234 | int seteuid(uid_t euid) | |
235 | { | |
236 | return(setreuid(-1,euid)); | |
237 | } | |
238 | #endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */ |