summaryrefslogtreecommitdiff
path: root/auth2.c
diff options
context:
space:
mode:
Diffstat (limited to 'auth2.c')
-rw-r--r--auth2.c93
1 files changed, 63 insertions, 30 deletions
diff --git a/auth2.c b/auth2.c
index f00f14764..b55bbcd95 100644
--- a/auth2.c
+++ b/auth2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2.c,v 1.126 2012/12/02 20:34:09 djm Exp $ */ 1/* $OpenBSD: auth2.c,v 1.129 2013/05/19 02:42:42 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -100,8 +100,12 @@ static void input_userauth_request(int, u_int32_t, void *);
100/* helper */ 100/* helper */
101static Authmethod *authmethod_lookup(Authctxt *, const char *); 101static Authmethod *authmethod_lookup(Authctxt *, const char *);
102static char *authmethods_get(Authctxt *authctxt); 102static char *authmethods_get(Authctxt *authctxt);
103static int method_allowed(Authctxt *, const char *); 103
104static int list_starts_with(const char *, const char *); 104#define MATCH_NONE 0 /* method or submethod mismatch */
105#define MATCH_METHOD 1 /* method matches (no submethod specified) */
106#define MATCH_BOTH 2 /* method and submethod match */
107#define MATCH_PARTIAL 3 /* method matches, submethod can't be checked */
108static int list_starts_with(const char *, const char *, const char *);
105 109
106char * 110char *
107auth2_read_banner(void) 111auth2_read_banner(void)
@@ -128,7 +132,7 @@ auth2_read_banner(void)
128 close(fd); 132 close(fd);
129 133
130 if (n != len) { 134 if (n != len) {
131 xfree(banner); 135 free(banner);
132 return (NULL); 136 return (NULL);
133 } 137 }
134 banner[n] = '\0'; 138 banner[n] = '\0';
@@ -164,8 +168,7 @@ userauth_banner(void)
164 userauth_send_banner(banner); 168 userauth_send_banner(banner);
165 169
166done: 170done:
167 if (banner) 171 free(banner);
168 xfree(banner);
169} 172}
170 173
171/* 174/*
@@ -210,7 +213,7 @@ input_service_request(int type, u_int32_t seq, void *ctxt)
210 debug("bad service request %s", service); 213 debug("bad service request %s", service);
211 packet_disconnect("bad service request %s", service); 214 packet_disconnect("bad service request %s", service);
212 } 215 }
213 xfree(service); 216 free(service);
214} 217}
215 218
216/*ARGSUSED*/ 219/*ARGSUSED*/
@@ -296,9 +299,9 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
296 } 299 }
297 userauth_finish(authctxt, authenticated, method, NULL); 300 userauth_finish(authctxt, authenticated, method, NULL);
298 301
299 xfree(service); 302 free(service);
300 xfree(user); 303 free(user);
301 xfree(method); 304 free(method);
302} 305}
303 306
304void 307void
@@ -324,14 +327,14 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
324 } 327 }
325 328
326 if (authenticated && options.num_auth_methods != 0) { 329 if (authenticated && options.num_auth_methods != 0) {
327 if (!auth2_update_methods_lists(authctxt, method)) { 330 if (!auth2_update_methods_lists(authctxt, method, submethod)) {
328 authenticated = 0; 331 authenticated = 0;
329 partial = 1; 332 partial = 1;
330 } 333 }
331 } 334 }
332 335
333 /* Log before sending the reply */ 336 /* Log before sending the reply */
334 auth_log(authctxt, authenticated, partial, method, submethod, " ssh2"); 337 auth_log(authctxt, authenticated, partial, method, submethod);
335 338
336 if (authctxt->postponed) 339 if (authctxt->postponed)
337 return; 340 return;
@@ -386,7 +389,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
386 packet_put_char(partial); 389 packet_put_char(partial);
387 packet_send(); 390 packet_send();
388 packet_write_wait(); 391 packet_write_wait();
389 xfree(methods); 392 free(methods);
390 } 393 }
391} 394}
392 395
@@ -395,8 +398,9 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
395 * methods list. Returns 1 if allowed, or no methods lists configured. 398 * methods list. Returns 1 if allowed, or no methods lists configured.
396 * 0 otherwise. 399 * 0 otherwise.
397 */ 400 */
398static int 401int
399method_allowed(Authctxt *authctxt, const char *method) 402auth2_method_allowed(Authctxt *authctxt, const char *method,
403 const char *submethod)
400{ 404{
401 u_int i; 405 u_int i;
402 406
@@ -407,7 +411,8 @@ method_allowed(Authctxt *authctxt, const char *method)
407 if (options.num_auth_methods == 0) 411 if (options.num_auth_methods == 0)
408 return 1; 412 return 1;
409 for (i = 0; i < authctxt->num_auth_methods; i++) { 413 for (i = 0; i < authctxt->num_auth_methods; i++) {
410 if (list_starts_with(authctxt->auth_methods[i], method)) 414 if (list_starts_with(authctxt->auth_methods[i], method,
415 submethod) != MATCH_NONE)
411 return 1; 416 return 1;
412 } 417 }
413 return 0; 418 return 0;
@@ -427,7 +432,8 @@ authmethods_get(Authctxt *authctxt)
427 if (authmethods[i]->enabled == NULL || 432 if (authmethods[i]->enabled == NULL ||
428 *(authmethods[i]->enabled) == 0) 433 *(authmethods[i]->enabled) == 0)
429 continue; 434 continue;
430 if (!method_allowed(authctxt, authmethods[i]->name)) 435 if (!auth2_method_allowed(authctxt, authmethods[i]->name,
436 NULL))
431 continue; 437 continue;
432 if (buffer_len(&b) > 0) 438 if (buffer_len(&b) > 0)
433 buffer_append(&b, ",", 1); 439 buffer_append(&b, ",", 1);
@@ -450,7 +456,8 @@ authmethod_lookup(Authctxt *authctxt, const char *name)
450 if (authmethods[i]->enabled != NULL && 456 if (authmethods[i]->enabled != NULL &&
451 *(authmethods[i]->enabled) != 0 && 457 *(authmethods[i]->enabled) != 0 &&
452 strcmp(name, authmethods[i]->name) == 0 && 458 strcmp(name, authmethods[i]->name) == 0 &&
453 method_allowed(authctxt, authmethods[i]->name)) 459 auth2_method_allowed(authctxt,
460 authmethods[i]->name, NULL))
454 return authmethods[i]; 461 return authmethods[i];
455 debug2("Unrecognized authentication method name: %s", 462 debug2("Unrecognized authentication method name: %s",
456 name ? name : "NULL"); 463 name ? name : "NULL");
@@ -465,7 +472,7 @@ authmethod_lookup(Authctxt *authctxt, const char *name)
465int 472int
466auth2_methods_valid(const char *_methods, int need_enable) 473auth2_methods_valid(const char *_methods, int need_enable)
467{ 474{
468 char *methods, *omethods, *method; 475 char *methods, *omethods, *method, *p;
469 u_int i, found; 476 u_int i, found;
470 int ret = -1; 477 int ret = -1;
471 478
@@ -476,6 +483,8 @@ auth2_methods_valid(const char *_methods, int need_enable)
476 omethods = methods = xstrdup(_methods); 483 omethods = methods = xstrdup(_methods);
477 while ((method = strsep(&methods, ",")) != NULL) { 484 while ((method = strsep(&methods, ",")) != NULL) {
478 for (found = i = 0; !found && authmethods[i] != NULL; i++) { 485 for (found = i = 0; !found && authmethods[i] != NULL; i++) {
486 if ((p = strchr(method, ':')) != NULL)
487 *p = '\0';
479 if (strcmp(method, authmethods[i]->name) != 0) 488 if (strcmp(method, authmethods[i]->name) != 0)
480 continue; 489 continue;
481 if (need_enable) { 490 if (need_enable) {
@@ -541,15 +550,30 @@ auth2_setup_methods_lists(Authctxt *authctxt)
541} 550}
542 551
543static int 552static int
544list_starts_with(const char *methods, const char *method) 553list_starts_with(const char *methods, const char *method,
554 const char *submethod)
545{ 555{
546 size_t l = strlen(method); 556 size_t l = strlen(method);
557 int match;
558 const char *p;
547 559
548 if (strncmp(methods, method, l) != 0) 560 if (strncmp(methods, method, l) != 0)
549 return 0; 561 return MATCH_NONE;
550 if (methods[l] != ',' && methods[l] != '\0') 562 p = methods + l;
551 return 0; 563 match = MATCH_METHOD;
552 return 1; 564 if (*p == ':') {
565 if (!submethod)
566 return MATCH_PARTIAL;
567 l = strlen(submethod);
568 p += 1;
569 if (strncmp(submethod, p, l))
570 return MATCH_NONE;
571 p += l;
572 match = MATCH_BOTH;
573 }
574 if (*p != ',' && *p != '\0')
575 return MATCH_NONE;
576 return match;
553} 577}
554 578
555/* 579/*
@@ -558,14 +582,21 @@ list_starts_with(const char *methods, const char *method)
558 * if it did. 582 * if it did.
559 */ 583 */
560static int 584static int
561remove_method(char **methods, const char *method) 585remove_method(char **methods, const char *method, const char *submethod)
562{ 586{
563 char *omethods = *methods; 587 char *omethods = *methods, *p;
564 size_t l = strlen(method); 588 size_t l = strlen(method);
589 int match;
565 590
566 if (!list_starts_with(omethods, method)) 591 match = list_starts_with(omethods, method, submethod);
592 if (match != MATCH_METHOD && match != MATCH_BOTH)
567 return 0; 593 return 0;
568 *methods = xstrdup(omethods + l + (omethods[l] == ',' ? 1 : 0)); 594 p = omethods + l;
595 if (submethod && match == MATCH_BOTH)
596 p += 1 + strlen(submethod); /* include colon */
597 if (*p == ',')
598 p++;
599 *methods = xstrdup(p);
569 free(omethods); 600 free(omethods);
570 return 1; 601 return 1;
571} 602}
@@ -577,13 +608,15 @@ remove_method(char **methods, const char *method)
577 * Returns 1 if the method completed any authentication list or 0 otherwise. 608 * Returns 1 if the method completed any authentication list or 0 otherwise.
578 */ 609 */
579int 610int
580auth2_update_methods_lists(Authctxt *authctxt, const char *method) 611auth2_update_methods_lists(Authctxt *authctxt, const char *method,
612 const char *submethod)
581{ 613{
582 u_int i, found = 0; 614 u_int i, found = 0;
583 615
584 debug3("%s: updating methods list after \"%s\"", __func__, method); 616 debug3("%s: updating methods list after \"%s\"", __func__, method);
585 for (i = 0; i < authctxt->num_auth_methods; i++) { 617 for (i = 0; i < authctxt->num_auth_methods; i++) {
586 if (!remove_method(&(authctxt->auth_methods[i]), method)) 618 if (!remove_method(&(authctxt->auth_methods[i]), method,
619 submethod))
587 continue; 620 continue;
588 found = 1; 621 found = 1;
589 if (*authctxt->auth_methods[i] == '\0') { 622 if (*authctxt->auth_methods[i] == '\0') {