]>
Commit | Line | Data |
---|---|---|
8efc0c15 | 1 | /* |
2 | ** | |
3 | ** OpenBSD emulation routines | |
4 | ** | |
5 | ** Damien Miller <djm@ibs.com.au> | |
6 | ** | |
1cbe6fb2 | 7 | ** Copyright 1999 Damien Miller |
8efc0c15 | 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 | ||
76a8e733 | 37 | #include "config.h" |
38 | ||
8efc0c15 | 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> | |
7b1cc56c | 47 | #include <sys/socket.h> |
48 | #include <sys/un.h> | |
8efc0c15 | 49 | #include <fcntl.h> |
50 | ||
8efc0c15 | 51 | #include "xmalloc.h" |
4cca272e | 52 | #include "ssh.h" |
d7a582ea | 53 | #include "bsd-misc.h" |
8efc0c15 | 54 | |
7b1cc56c | 55 | #ifndef offsetof |
56 | #define offsetof(type, member) ((size_t) &((type *)0)->member) | |
57 | #endif | |
58 | ||
fb723d82 | 59 | #ifndef HAVE_ARC4RANDOM |
60 | ||
a408af76 | 61 | typedef struct |
62 | { | |
63 | unsigned int s[256]; | |
64 | int i; | |
65 | int j; | |
66 | } rc4_t; | |
67 | ||
8efc0c15 | 68 | void get_random_bytes(unsigned char *buf, int len); |
a408af76 | 69 | void rc4_key(rc4_t *r, unsigned char *key, int len); |
70 | void rc4_getbytes(rc4_t *r, unsigned char *buffer, int len); | |
8efc0c15 | 71 | |
72 | static rc4_t *rc4 = NULL; | |
73 | ||
a408af76 | 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 | ||
0183ea1c | 113 | unsigned int arc4random(void) |
8efc0c15 | 114 | { |
0183ea1c | 115 | unsigned int r; |
8efc0c15 | 116 | |
117 | if (rc4 == NULL) | |
118 | arc4random_stir(); | |
119 | ||
0183ea1c | 120 | rc4_getbytes(rc4, (unsigned char *)&r, sizeof(r)); |
8efc0c15 | 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 | { | |
7b1cc56c | 138 | static int random_pool; |
8efc0c15 | 139 | int c; |
4cca272e | 140 | #ifdef HAVE_EGD |
141 | char egd_message[2] = { 0x02, 0x00 }; | |
7b1cc56c | 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 | ||
530f1889 | 152 | strcpy(addr.sun_path, RANDOM_POOL); |
7b1cc56c | 153 | |
154 | addr_len = offsetof(struct sockaddr_un, sun_path) + sizeof(RANDOM_POOL); | |
155 | ||
156 | random_pool = socket(AF_UNIX, SOCK_STREAM, 0); | |
8efc0c15 | 157 | |
4cca272e | 158 | if (random_pool == -1) |
7b1cc56c | 159 | fatal("Couldn't create AF_UNIX socket: %s", strerror(errno)); |
8efc0c15 | 160 | |
7b1cc56c | 161 | if (connect(random_pool, (struct sockaddr*)&addr, addr_len) == -1) |
b609e28f | 162 | fatal("Couldn't connect to EGD socket \"%s\": %s", addr.sun_path, strerror(errno)); |
7b1cc56c | 163 | |
4cca272e | 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; | |
a408af76 | 169 | |
170 | c = atomicio(write, random_pool, egd_message, sizeof(egd_message)); | |
4cca272e | 171 | if (c == -1) |
172 | fatal("Couldn't write to EGD socket \"%s\": %s", RANDOM_POOL, strerror(errno)); | |
7b1cc56c | 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 | ||
4cca272e | 180 | #endif /* HAVE_EGD */ |
181 | ||
a408af76 | 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)); | |
4cca272e | 185 | |
186 | close(random_pool); | |
8efc0c15 | 187 | } |
fb723d82 | 188 | #endif /* !HAVE_ARC4RANDOM */ |
8efc0c15 | 189 | |
fb723d82 | 190 | #ifndef HAVE_SETPROCTITLE |
191 | void setproctitle(const char *fmt, ...) | |
192 | { | |
193 | /* FIXME */ | |
194 | } | |
195 | #endif /* !HAVE_SETPROCTITLE */ | |
1647c2b5 | 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 */ | |
a5c9cd31 | 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) */ |