|
@@ -85,6 +85,7 @@ static char hex2num (char c)
|
85
|
85
|
if (c >= '0' && c <= '9') return c - '0';
|
86
|
86
|
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
87
|
87
|
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
|
|
88
|
+ return 0;
|
88
|
89
|
}
|
89
|
90
|
|
90
|
91
|
static char num2hex (char c)
|
|
@@ -139,12 +140,24 @@ static char* url_encode (char* buf, size_t len, const char *input)
|
139
|
140
|
return buf;
|
140
|
141
|
}
|
141
|
142
|
|
142
|
|
-static void handle_forward (srs_t *srs, FILE *fp, const char *address, const char *domain)
|
|
143
|
+static void handle_forward (srs_t *srs, FILE *fp, const char *address, const char *domain, const char **excludes)
|
143
|
144
|
{
|
144
|
145
|
int result;
|
|
146
|
+ size_t addrlen;
|
145
|
147
|
char value[1024];
|
146
|
148
|
char outputbuf[1024], *output;
|
147
|
149
|
|
|
150
|
+ addrlen = strlen(address);
|
|
151
|
+ for(; *excludes; excludes++) {
|
|
152
|
+ size_t len;
|
|
153
|
+ len = strlen(*excludes);
|
|
154
|
+ if (len >= addrlen) continue;
|
|
155
|
+ if (strcasecmp(*excludes, &address[addrlen - len]) == 0 && (**excludes == '.' || address[addrlen - len - 1] == '@')) {
|
|
156
|
+ fputs ("500 Domain excluded from SRS\n", fp);
|
|
157
|
+ fflush (fp);
|
|
158
|
+ return;
|
|
159
|
+ }
|
|
160
|
+ }
|
148
|
161
|
result = srs_forward(srs, value, sizeof(value), address, domain);
|
149
|
162
|
if (result == SRS_SUCCESS) {
|
150
|
163
|
output = url_encode(outputbuf, sizeof(outputbuf), value);
|
|
@@ -158,7 +171,7 @@ static void handle_forward (srs_t *srs, FILE *fp, const char *address, const cha
|
158
|
171
|
fflush (fp);
|
159
|
172
|
}
|
160
|
173
|
|
161
|
|
-static void handle_reverse (srs_t *srs, FILE *fp, const char *address, const char *domain)
|
|
174
|
+static void handle_reverse (srs_t *srs, FILE *fp, const char *address, const char *domain, const char **excludes)
|
162
|
175
|
{
|
163
|
176
|
int result;
|
164
|
177
|
char value[1024];
|
|
@@ -188,7 +201,7 @@ static void show_help ()
|
188
|
201
|
"\n"
|
189
|
202
|
"Usage: %s -s<file> -d<domain> [other options]\n"
|
190
|
203
|
"Options:\n"
|
191
|
|
- " -s<file> read secret from file (required)\n"
|
|
204
|
+ " -s<file> read secrets from file (required)\n"
|
192
|
205
|
" -d<domain> set domain name for rewrite (required)\n"
|
193
|
206
|
" -f<port> set port for the forward SRS lookup (default: 10001)\n"
|
194
|
207
|
" -r<port> set port for the reverse SRS lookup (default: 10002)\n"
|
|
@@ -196,6 +209,7 @@ static void show_help ()
|
196
|
209
|
" -c<dir> chroot to <dir> (default: none)\n"
|
197
|
210
|
" -u<user> switch user id after port bind (default: none)\n"
|
198
|
211
|
" -t<seconds> timeout for idle client connections (default: 1800)\n"
|
|
212
|
+ " -X<domain> exclude additional domain from address rewriting\n"
|
199
|
213
|
" -D fork into background\n"
|
200
|
214
|
" -4 force IPv4 socket (default: any)\n"
|
201
|
215
|
" -6 force IPv6 socket (default: any)\n"
|
|
@@ -206,7 +220,7 @@ static void show_help ()
|
206
|
220
|
);
|
207
|
221
|
}
|
208
|
222
|
|
209
|
|
-typedef void(*handle_t)(srs_t*, FILE*, const char*, const char*);
|
|
223
|
+typedef void(*handle_t)(srs_t*, FILE*, const char*, const char*, const char**);
|
210
|
224
|
|
211
|
225
|
int main (int argc, char **argv)
|
212
|
226
|
{
|
|
@@ -216,18 +230,21 @@ int main (int argc, char **argv)
|
216
|
230
|
*user = NULL, *domain = NULL, *chroot_dir = NULL;
|
217
|
231
|
int forward_sock, reverse_sock;
|
218
|
232
|
char *secret_file = NULL, *pid_file = NULL;
|
219
|
|
- FILE *pf = NULL;
|
|
233
|
+ FILE *pf = NULL, *sf = NULL;
|
220
|
234
|
struct passwd *pwd = NULL;
|
221
|
|
- char secret[1024];
|
|
235
|
+ char secretbuf[1024], *secret = NULL;
|
222
|
236
|
char *tmp;
|
223
|
237
|
srs_t *srs;
|
224
|
238
|
struct pollfd fds[3];
|
|
239
|
+ const char **excludes;
|
|
240
|
+ size_t s1 = 0, s2 = 1;
|
225
|
241
|
handle_t handler[2] = { handle_forward, handle_reverse };
|
226
|
242
|
|
|
243
|
+ excludes = (const char**)calloc(1, sizeof(char*));
|
227
|
244
|
tmp = strrchr(argv[0], '/');
|
228
|
245
|
if (tmp) self = strdup(tmp + 1); else self = strdup(argv[0]);
|
229
|
246
|
|
230
|
|
- while ((opt = getopt(argc, argv, "46d:f:r:s:u:t:p:c:Dhv")) != -1) {
|
|
247
|
+ while ((opt = getopt(argc, argv, "46d:f:r:s:u:t:p:c:X::Dhv")) != -1) {
|
231
|
248
|
switch (opt) {
|
232
|
249
|
case '?':
|
233
|
250
|
return EXIT_FAILURE;
|
|
@@ -259,17 +276,35 @@ int main (int argc, char **argv)
|
259
|
276
|
user = strdup(optarg);
|
260
|
277
|
break;
|
261
|
278
|
case 'c':
|
262
|
|
- chroot_dir = strdup(optarg);
|
263
|
|
- break;
|
|
279
|
+ chroot_dir = strdup(optarg);
|
|
280
|
+ break;
|
264
|
281
|
case 'D':
|
265
|
282
|
daemonize = TRUE;
|
266
|
283
|
break;
|
267
|
284
|
case 'h':
|
268
|
|
- show_help();
|
|
285
|
+ show_help();
|
269
|
286
|
return EXIT_SUCCESS;
|
|
287
|
+ case 'X':
|
|
288
|
+ if (optarg != NULL) {
|
|
289
|
+ tmp = strtok(optarg, ",; \t\r\n");
|
|
290
|
+ while (tmp) {
|
|
291
|
+ if (s1 + 1 >= s2) {
|
|
292
|
+ s2 *= 2;
|
|
293
|
+ excludes = (const char **)realloc(excludes, s2 * sizeof(char*));
|
|
294
|
+ if (excludes == NULL) {
|
|
295
|
+ fprintf (stderr, "%s: Out of memory\n\n", self);
|
|
296
|
+ return EXIT_FAILURE;
|
|
297
|
+ }
|
|
298
|
+ }
|
|
299
|
+ excludes[s1++] = strdup(tmp);
|
|
300
|
+ tmp = strtok(NULL, ",; \t\r\n");
|
|
301
|
+ }
|
|
302
|
+ excludes[s1] = NULL;
|
|
303
|
+ }
|
|
304
|
+ break;
|
270
|
305
|
case 'v':
|
271
|
|
- fprintf (stdout, "%s\n", VERSION);
|
272
|
|
- return EXIT_SUCCESS;
|
|
306
|
+ fprintf (stdout, "%s\n", VERSION);
|
|
307
|
+ return EXIT_SUCCESS;
|
273
|
308
|
}
|
274
|
309
|
}
|
275
|
310
|
if (domain == NULL) {
|
|
@@ -291,18 +326,11 @@ int main (int argc, char **argv)
|
291
|
326
|
/* Read secret. The default installation makes this root accessible only. */
|
292
|
327
|
if (secret_file != NULL) {
|
293
|
328
|
size_t len;
|
294
|
|
- FILE *fp = fopen(secret_file, "rb");
|
295
|
|
- if (fp == NULL) {
|
|
329
|
+ sf = fopen(secret_file, "rb");
|
|
330
|
+ if (sf == NULL) {
|
296
|
331
|
fprintf (stderr, "%s: Cannot open file with secret: %s\n", self, secret_file);
|
297
|
332
|
return EXIT_FAILURE;
|
298
|
333
|
}
|
299
|
|
- len = fread(secret, 1, sizeof(secret) - 1, fp);
|
300
|
|
- if (len == 0 || len > sizeof(secret) - 1) {
|
301
|
|
- fprintf (stderr, "%s: Cannot read secret from file: %s\n", self, secret_file);
|
302
|
|
- return EXIT_FAILURE;
|
303
|
|
- }
|
304
|
|
- secret[len] = 0;
|
305
|
|
- fclose (fp);
|
306
|
334
|
} else {
|
307
|
335
|
fprintf (stderr, "%s: You must set a secret (-s)\n", self);
|
308
|
336
|
show_help();
|
|
@@ -370,7 +398,12 @@ int main (int argc, char **argv)
|
370
|
398
|
}
|
371
|
399
|
|
372
|
400
|
srs = srs_new();
|
373
|
|
- srs_add_secret (srs, secret);
|
|
401
|
+ while ((secret = fgets(secretbuf, sizeof(secretbuf), sf))) {
|
|
402
|
+ secret = strtok(secret, "\r\n");
|
|
403
|
+ if (secret)
|
|
404
|
+ srs_add_secret (srs, secret);
|
|
405
|
+ }
|
|
406
|
+ fclose (sf);
|
374
|
407
|
srs_set_separator (srs, '+');
|
375
|
408
|
|
376
|
409
|
fds[0].fd = forward_sock;
|
|
@@ -416,7 +449,7 @@ int main (int argc, char **argv)
|
416
|
449
|
}
|
417
|
450
|
key = url_decode(keybuf, sizeof(keybuf), token);
|
418
|
451
|
if (!key) break;
|
419
|
|
- handler[i](srs, fp, key, domain);
|
|
452
|
+ handler[i](srs, fp, key, domain, excludes);
|
420
|
453
|
if (poll(&fds[2], 1, timeout * 1000) <= 0) break;
|
421
|
454
|
line = fgets(linebuf, sizeof(linebuf), fp);
|
422
|
455
|
}
|