summaryrefslogtreecommitdiff
path: root/auth-options.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2018-08-24 12:49:36 +0100
committerColin Watson <cjwatson@debian.org>2018-08-24 12:49:36 +0100
commite6547182a54f0f268ee36e7c99319eeddffbaff2 (patch)
tree417527229ad3f3764ba71ea383f478a168895087 /auth-options.c
parented6ae9c1a014a08ff5db3d768f01f2e427eeb476 (diff)
parent71508e06fab14bc415a79a08f5535ad7bffa93d9 (diff)
Import openssh_7.8p1.orig.tar.gz
Diffstat (limited to 'auth-options.c')
-rw-r--r--auth-options.c154
1 files changed, 107 insertions, 47 deletions
diff --git a/auth-options.c b/auth-options.c
index b528c197a..27c0eb05e 100644
--- a/auth-options.c
+++ b/auth-options.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth-options.c,v 1.78 2018/03/14 05:35:40 djm Exp $ */ 1/* $OpenBSD: auth-options.c,v 1.83 2018/06/19 02:59:41 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2018 Damien Miller <djm@mindrot.org> 3 * Copyright (c) 2018 Damien Miller <djm@mindrot.org>
4 * 4 *
@@ -283,6 +283,10 @@ sshauthopt_free(struct sshauthopt *opts)
283 free(opts->permitopen[i]); 283 free(opts->permitopen[i]);
284 free(opts->permitopen); 284 free(opts->permitopen);
285 285
286 for (i = 0; i < opts->npermitlisten; i++)
287 free(opts->permitlisten[i]);
288 free(opts->permitlisten);
289
286 explicit_bzero(opts, sizeof(*opts)); 290 explicit_bzero(opts, sizeof(*opts));
287 free(opts); 291 free(opts);
288} 292}
@@ -304,10 +308,82 @@ sshauthopt_new_with_keys_defaults(void)
304 return ret; 308 return ret;
305} 309}
306 310
311/*
312 * Parse and record a permitopen/permitlisten directive.
313 * Return 0 on success. Return -1 on failure and sets *errstrp to error reason.
314 */
315static int
316handle_permit(const char **optsp, int allow_bare_port,
317 char ***permitsp, size_t *npermitsp, const char **errstrp)
318{
319 char *opt, *tmp, *cp, *host, **permits = *permitsp;
320 size_t npermits = *npermitsp;
321 const char *errstr = "unknown error";
322
323 if (npermits > INT_MAX) {
324 *errstrp = "too many permission directives";
325 return -1;
326 }
327 if ((opt = opt_dequote(optsp, &errstr)) == NULL) {
328 return -1;
329 }
330 if (allow_bare_port && strchr(opt, ':') == NULL) {
331 /*
332 * Allow a bare port number in permitlisten to indicate a
333 * listen_host wildcard.
334 */
335 if (asprintf(&tmp, "*:%s", opt) < 0) {
336 *errstrp = "memory allocation failed";
337 return -1;
338 }
339 free(opt);
340 opt = tmp;
341 }
342 if ((tmp = strdup(opt)) == NULL) {
343 free(opt);
344 *errstrp = "memory allocation failed";
345 return -1;
346 }
347 cp = tmp;
348 /* validate syntax before recording it. */
349 host = hpdelim(&cp);
350 if (host == NULL || strlen(host) >= NI_MAXHOST) {
351 free(tmp);
352 free(opt);
353 *errstrp = "invalid permission hostname";
354 return -1;
355 }
356 /*
357 * don't want to use permitopen_port to avoid
358 * dependency on channels.[ch] here.
359 */
360 if (cp == NULL ||
361 (strcmp(cp, "*") != 0 && a2port(cp) <= 0)) {
362 free(tmp);
363 free(opt);
364 *errstrp = "invalid permission port";
365 return -1;
366 }
367 /* XXX - add streamlocal support */
368 free(tmp);
369 /* Record it */
370 if ((permits = recallocarray(permits, npermits, npermits + 1,
371 sizeof(*permits))) == NULL) {
372 free(opt);
373 /* NB. don't update *permitsp if alloc fails */
374 *errstrp = "memory allocation failed";
375 return -1;
376 }
377 permits[npermits++] = opt;
378 *permitsp = permits;
379 *npermitsp = npermits;
380 return 0;
381}
382
307struct sshauthopt * 383struct sshauthopt *
308sshauthopt_parse(const char *opts, const char **errstrp) 384sshauthopt_parse(const char *opts, const char **errstrp)
309{ 385{
310 char **oarray, *opt, *cp, *tmp, *host; 386 char **oarray, *opt, *cp, *tmp;
311 int r; 387 int r;
312 struct sshauthopt *ret = NULL; 388 struct sshauthopt *ret = NULL;
313 const char *errstr = "unknown error"; 389 const char *errstr = "unknown error";
@@ -394,7 +470,7 @@ sshauthopt_parse(const char *opts, const char **errstrp)
394 goto fail; 470 goto fail;
395 } 471 }
396 for (cp = opt; cp < tmp; cp++) { 472 for (cp = opt; cp < tmp; cp++) {
397 if (!isalnum((u_char)*cp)) { 473 if (!isalnum((u_char)*cp) && *cp != '_') {
398 free(opt); 474 free(opt);
399 errstr = "invalid environment string"; 475 errstr = "invalid environment string";
400 goto fail; 476 goto fail;
@@ -410,48 +486,13 @@ sshauthopt_parse(const char *opts, const char **errstrp)
410 } 486 }
411 ret->env[ret->nenv++] = opt; 487 ret->env[ret->nenv++] = opt;
412 } else if (opt_match(&opts, "permitopen")) { 488 } else if (opt_match(&opts, "permitopen")) {
413 if (ret->npermitopen > INT_MAX) { 489 if (handle_permit(&opts, 0, &ret->permitopen,
414 errstr = "too many permitopens"; 490 &ret->npermitopen, &errstr) != 0)
415 goto fail;
416 }
417 if ((opt = opt_dequote(&opts, &errstr)) == NULL)
418 goto fail;
419 if ((tmp = strdup(opt)) == NULL) {
420 free(opt);
421 goto alloc_fail;
422 }
423 cp = tmp;
424 /* validate syntax of permitopen before recording it. */
425 host = hpdelim(&cp);
426 if (host == NULL || strlen(host) >= NI_MAXHOST) {
427 free(tmp);
428 free(opt);
429 errstr = "invalid permitopen hostname";
430 goto fail; 491 goto fail;
431 } 492 } else if (opt_match(&opts, "permitlisten")) {
432 /* 493 if (handle_permit(&opts, 1, &ret->permitlisten,
433 * don't want to use permitopen_port to avoid 494 &ret->npermitlisten, &errstr) != 0)
434 * dependency on channels.[ch] here.
435 */
436 if (cp == NULL ||
437 (strcmp(cp, "*") != 0 && a2port(cp) <= 0)) {
438 free(tmp);
439 free(opt);
440 errstr = "invalid permitopen port";
441 goto fail; 495 goto fail;
442 }
443 /* XXX - add streamlocal support */
444 free(tmp);
445 /* Record it */
446 oarray = ret->permitopen;
447 if ((ret->permitopen = recallocarray(ret->permitopen,
448 ret->npermitopen, ret->npermitopen + 1,
449 sizeof(*ret->permitopen))) == NULL) {
450 free(opt);
451 ret->permitopen = oarray;
452 goto alloc_fail;
453 }
454 ret->permitopen[ret->npermitopen++] = opt;
455 } else if (opt_match(&opts, "tunnel")) { 496 } else if (opt_match(&opts, "tunnel")) {
456 if ((opt = opt_dequote(&opts, &errstr)) == NULL) 497 if ((opt = opt_dequote(&opts, &errstr)) == NULL)
457 goto fail; 498 goto fail;
@@ -554,7 +595,10 @@ sshauthopt_merge(const struct sshauthopt *primary,
554 if (tmp != NULL && (ret->required_from_host_keys = strdup(tmp)) == NULL) 595 if (tmp != NULL && (ret->required_from_host_keys = strdup(tmp)) == NULL)
555 goto alloc_fail; 596 goto alloc_fail;
556 597
557 /* force_tun_device, permitopen and environment prefer the primary. */ 598 /*
599 * force_tun_device, permitopen/permitlisten and environment all
600 * prefer the primary.
601 */
558 ret->force_tun_device = primary->force_tun_device; 602 ret->force_tun_device = primary->force_tun_device;
559 if (ret->force_tun_device == -1) 603 if (ret->force_tun_device == -1)
560 ret->force_tun_device = additional->force_tun_device; 604 ret->force_tun_device = additional->force_tun_device;
@@ -577,6 +621,16 @@ sshauthopt_merge(const struct sshauthopt *primary,
577 goto alloc_fail; 621 goto alloc_fail;
578 } 622 }
579 623
624 if (primary->npermitlisten > 0) {
625 if (dup_strings(&ret->permitlisten, &ret->npermitlisten,
626 primary->permitlisten, primary->npermitlisten) != 0)
627 goto alloc_fail;
628 } else if (additional->npermitlisten > 0) {
629 if (dup_strings(&ret->permitlisten, &ret->npermitlisten,
630 additional->permitlisten, additional->npermitlisten) != 0)
631 goto alloc_fail;
632 }
633
580 /* Flags are logical-AND (i.e. must be set in both for permission) */ 634 /* Flags are logical-AND (i.e. must be set in both for permission) */
581#define OPTFLAG(x) ret->x = (primary->x == 1) && (additional->x == 1) 635#define OPTFLAG(x) ret->x = (primary->x == 1) && (additional->x == 1)
582 OPTFLAG(permit_port_forwarding_flag); 636 OPTFLAG(permit_port_forwarding_flag);
@@ -669,7 +723,9 @@ sshauthopt_copy(const struct sshauthopt *orig)
669 723
670 if (dup_strings(&ret->env, &ret->nenv, orig->env, orig->nenv) != 0 || 724 if (dup_strings(&ret->env, &ret->nenv, orig->env, orig->nenv) != 0 ||
671 dup_strings(&ret->permitopen, &ret->npermitopen, 725 dup_strings(&ret->permitopen, &ret->npermitopen,
672 orig->permitopen, orig->npermitopen) != 0) { 726 orig->permitopen, orig->npermitopen) != 0 ||
727 dup_strings(&ret->permitlisten, &ret->npermitlisten,
728 orig->permitlisten, orig->npermitlisten) != 0) {
673 sshauthopt_free(ret); 729 sshauthopt_free(ret);
674 return NULL; 730 return NULL;
675 } 731 }
@@ -805,7 +861,9 @@ sshauthopt_serialise(const struct sshauthopt *opts, struct sshbuf *m,
805 if ((r = serialise_array(m, opts->env, 861 if ((r = serialise_array(m, opts->env,
806 untrusted ? 0 : opts->nenv)) != 0 || 862 untrusted ? 0 : opts->nenv)) != 0 ||
807 (r = serialise_array(m, opts->permitopen, 863 (r = serialise_array(m, opts->permitopen,
808 untrusted ? 0 : opts->npermitopen)) != 0) 864 untrusted ? 0 : opts->npermitopen)) != 0 ||
865 (r = serialise_array(m, opts->permitlisten,
866 untrusted ? 0 : opts->npermitlisten)) != 0)
809 return r; 867 return r;
810 868
811 /* success */ 869 /* success */
@@ -859,7 +917,9 @@ sshauthopt_deserialise(struct sshbuf *m, struct sshauthopt **optsp)
859 /* Array options */ 917 /* Array options */
860 if ((r = deserialise_array(m, &opts->env, &opts->nenv)) != 0 || 918 if ((r = deserialise_array(m, &opts->env, &opts->nenv)) != 0 ||
861 (r = deserialise_array(m, 919 (r = deserialise_array(m,
862 &opts->permitopen, &opts->npermitopen)) != 0) 920 &opts->permitopen, &opts->npermitopen)) != 0 ||
921 (r = deserialise_array(m,
922 &opts->permitlisten, &opts->npermitlisten)) != 0)
863 goto out; 923 goto out;
864 924
865 /* success */ 925 /* success */