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