diff options
Diffstat (limited to 'bsd-misc.c')
-rw-r--r-- | bsd-misc.c | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/bsd-misc.c b/bsd-misc.c new file mode 100644 index 000000000..c952fd0f3 --- /dev/null +++ b/bsd-misc.c | |||
@@ -0,0 +1,214 @@ | |||
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> | ||
44 | #include <sys/socket.h> | ||
45 | #include <sys/un.h> | ||
46 | #include <fcntl.h> | ||
47 | |||
48 | #include "xmalloc.h" | ||
49 | #include "ssh.h" | ||
50 | #include "config.h" | ||
51 | #include "bsd-misc.h" | ||
52 | |||
53 | #ifndef offsetof | ||
54 | #define offsetof(type, member) ((size_t) &((type *)0)->member) | ||
55 | #endif | ||
56 | |||
57 | #ifndef HAVE_ARC4RANDOM | ||
58 | |||
59 | typedef struct | ||
60 | { | ||
61 | unsigned int s[256]; | ||
62 | int i; | ||
63 | int j; | ||
64 | } rc4_t; | ||
65 | |||
66 | void get_random_bytes(unsigned char *buf, int len); | ||
67 | void rc4_key(rc4_t *r, unsigned char *key, int len); | ||
68 | void rc4_getbytes(rc4_t *r, unsigned char *buffer, int len); | ||
69 | |||
70 | static rc4_t *rc4 = NULL; | ||
71 | |||
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 | |||
111 | unsigned int arc4random(void) | ||
112 | { | ||
113 | unsigned int r; | ||
114 | |||
115 | if (rc4 == NULL) | ||
116 | arc4random_stir(); | ||
117 | |||
118 | rc4_getbytes(rc4, (unsigned char *)&r, sizeof(r)); | ||
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 | { | ||
136 | static int random_pool; | ||
137 | int c; | ||
138 | #ifdef HAVE_EGD | ||
139 | char egd_message[2] = { 0x02, 0x00 }; | ||
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 | |||
150 | strcpy(addr.sun_path, RANDOM_POOL); | ||
151 | |||
152 | addr_len = offsetof(struct sockaddr_un, sun_path) + sizeof(RANDOM_POOL); | ||
153 | |||
154 | random_pool = socket(AF_UNIX, SOCK_STREAM, 0); | ||
155 | |||
156 | if (random_pool == -1) | ||
157 | fatal("Couldn't create AF_UNIX socket: %s", strerror(errno)); | ||
158 | |||
159 | if (connect(random_pool, (struct sockaddr*)&addr, addr_len) == -1) | ||
160 | fatal("Couldn't connect to EGD socket \"%s\": %s", addr.sun_path, strerror(errno)); | ||
161 | |||
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; | ||
167 | |||
168 | c = atomicio(write, random_pool, egd_message, sizeof(egd_message)); | ||
169 | if (c == -1) | ||
170 | fatal("Couldn't write to EGD socket \"%s\": %s", RANDOM_POOL, strerror(errno)); | ||
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 | |||
178 | #endif /* HAVE_EGD */ | ||
179 | |||
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)); | ||
183 | |||
184 | close(random_pool); | ||
185 | } | ||
186 | #endif /* !HAVE_ARC4RANDOM */ | ||
187 | |||
188 | #ifndef HAVE_SETPROCTITLE | ||
189 | void setproctitle(const char *fmt, ...) | ||
190 | { | ||
191 | /* FIXME */ | ||
192 | } | ||
193 | #endif /* !HAVE_SETPROCTITLE */ | ||
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 */ | ||