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 d25940036..6ed8f042b 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*/
@@ -290,9 +293,9 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
290 } 293 }
291 userauth_finish(authctxt, authenticated, method, NULL); 294 userauth_finish(authctxt, authenticated, method, NULL);
292 295
293 xfree(service); 296 free(service);
294 xfree(user); 297 free(user);
295 xfree(method); 298 free(method);
296} 299}
297 300
298void 301void
@@ -318,14 +321,14 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
318 } 321 }
319 322
320 if (authenticated && options.num_auth_methods != 0) { 323 if (authenticated && options.num_auth_methods != 0) {
321 if (!auth2_update_methods_lists(authctxt, method)) { 324 if (!auth2_update_methods_lists(authctxt, method, submethod)) {
322 authenticated = 0; 325 authenticated = 0;
323 partial = 1; 326 partial = 1;
324 } 327 }
325 } 328 }
326 329
327 /* Log before sending the reply */ 330 /* Log before sending the reply */
328 auth_log(authctxt, authenticated, partial, method, submethod, " ssh2"); 331 auth_log(authctxt, authenticated, partial, method, submethod);
329 332
330 if (authctxt->postponed) 333 if (authctxt->postponed)
331 return; 334 return;
@@ -380,7 +383,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
380 packet_put_char(partial); 383 packet_put_char(partial);
381 packet_send(); 384 packet_send();
382 packet_write_wait(); 385 packet_write_wait();
383 xfree(methods); 386 free(methods);
384 } 387 }
385} 388}
386 389
@@ -389,8 +392,9 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
389 * methods list. Returns 1 if allowed, or no methods lists configured. 392 * methods list. Returns 1 if allowed, or no methods lists configured.
390 * 0 otherwise. 393 * 0 otherwise.
391 */ 394 */
392static int 395int
393method_allowed(Authctxt *authctxt, const char *method) 396auth2_method_allowed(Authctxt *authctxt, const char *method,
397 const char *submethod)
394{ 398{
395 u_int i; 399 u_int i;
396 400
@@ -401,7 +405,8 @@ method_allowed(Authctxt *authctxt, const char *method)
401 if (options.num_auth_methods == 0) 405 if (options.num_auth_methods == 0)
402 return 1; 406 return 1;
403 for (i = 0; i < authctxt->num_auth_methods; i++) { 407 for (i = 0; i < authctxt->num_auth_methods; i++) {
404 if (list_starts_with(authctxt->auth_methods[i], method)) 408 if (list_starts_with(authctxt->auth_methods[i], method,
409 submethod) != MATCH_NONE)
405 return 1; 410 return 1;
406 } 411 }
407 return 0; 412 return 0;
@@ -421,7 +426,8 @@ authmethods_get(Authctxt *authctxt)
421 if (authmethods[i]->enabled == NULL || 426 if (authmethods[i]->enabled == NULL ||
422 *(authmethods[i]->enabled) == 0) 427 *(authmethods[i]->enabled) == 0)
423 continue; 428 continue;
424 if (!method_allowed(authctxt, authmethods[i]->name)) 429 if (!auth2_method_allowed(authctxt, authmethods[i]->name,
430 NULL))
425 continue; 431 continue;
426 if (buffer_len(&b) > 0) 432 if (buffer_len(&b) > 0)
427 buffer_append(&b, ",", 1); 433 buffer_append(&b, ",", 1);
@@ -444,7 +450,8 @@ authmethod_lookup(Authctxt *authctxt, const char *name)
444 if (authmethods[i]->enabled != NULL && 450 if (authmethods[i]->enabled != NULL &&
445 *(authmethods[i]->enabled) != 0 && 451 *(authmethods[i]->enabled) != 0 &&
446 strcmp(name, authmethods[i]->name) == 0 && 452 strcmp(name, authmethods[i]->name) == 0 &&
447 method_allowed(authctxt, authmethods[i]->name)) 453 auth2_method_allowed(authctxt,
454 authmethods[i]->name, NULL))
448 return authmethods[i]; 455 return authmethods[i];
449 debug2("Unrecognized authentication method name: %s", 456 debug2("Unrecognized authentication method name: %s",
450 name ? name : "NULL"); 457 name ? name : "NULL");
@@ -459,7 +466,7 @@ authmethod_lookup(Authctxt *authctxt, const char *name)
459int 466int
460auth2_methods_valid(const char *_methods, int need_enable) 467auth2_methods_valid(const char *_methods, int need_enable)
461{ 468{
462 char *methods, *omethods, *method; 469 char *methods, *omethods, *method, *p;
463 u_int i, found; 470 u_int i, found;
464 int ret = -1; 471 int ret = -1;
465 472
@@ -470,6 +477,8 @@ auth2_methods_valid(const char *_methods, int need_enable)
470 omethods = methods = xstrdup(_methods); 477 omethods = methods = xstrdup(_methods);
471 while ((method = strsep(&methods, ",")) != NULL) { 478 while ((method = strsep(&methods, ",")) != NULL) {
472 for (found = i = 0; !found && authmethods[i] != NULL; i++) { 479 for (found = i = 0; !found && authmethods[i] != NULL; i++) {
480 if ((p = strchr(method, ':')) != NULL)
481 *p = '\0';
473 if (strcmp(method, authmethods[i]->name) != 0) 482 if (strcmp(method, authmethods[i]->name) != 0)
474 continue; 483 continue;
475 if (need_enable) { 484 if (need_enable) {
@@ -535,15 +544,30 @@ auth2_setup_methods_lists(Authctxt *authctxt)
535} 544}
536 545
537static int 546static int
538list_starts_with(const char *methods, const char *method) 547list_starts_with(const char *methods, const char *method,
548 const char *submethod)
539{ 549{
540 size_t l = strlen(method); 550 size_t l = strlen(method);
551 int match;
552 const char *p;
541 553
542 if (strncmp(methods, method, l) != 0) 554 if (strncmp(methods, method, l) != 0)
543 return 0; 555 return MATCH_NONE;
544 if (methods[l] != ',' && methods[l] != '\0') 556 p = methods + l;
545 return 0; 557 match = MATCH_METHOD;
546 return 1; 558 if (*p == ':') {
559 if (!submethod)
560 return MATCH_PARTIAL;
561 l = strlen(submethod);
562 p += 1;
563 if (strncmp(submethod, p, l))
564 return MATCH_NONE;
565 p += l;
566 match = MATCH_BOTH;
567 }
568 if (*p != ',' && *p != '\0')
569 return MATCH_NONE;
570 return match;
547} 571}
548 572
549/* 573/*
@@ -552,14 +576,21 @@ list_starts_with(const char *methods, const char *method)
552 * if it did. 576 * if it did.
553 */ 577 */
554static int 578static int
555remove_method(char **methods, const char *method) 579remove_method(char **methods, const char *method, const char *submethod)
556{ 580{
557 char *omethods = *methods; 581 char *omethods = *methods, *p;
558 size_t l = strlen(method); 582 size_t l = strlen(method);
583 int match;
559 584
560 if (!list_starts_with(omethods, method)) 585 match = list_starts_with(omethods, method, submethod);
586 if (match != MATCH_METHOD && match != MATCH_BOTH)
561 return 0; 587 return 0;
562 *methods = xstrdup(omethods + l + (omethods[l] == ',' ? 1 : 0)); 588 p = omethods + l;
589 if (submethod && match == MATCH_BOTH)
590 p += 1 + strlen(submethod); /* include colon */
591 if (*p == ',')
592 p++;
593 *methods = xstrdup(p);
563 free(omethods); 594 free(omethods);
564 return 1; 595 return 1;
565} 596}
@@ -571,13 +602,15 @@ remove_method(char **methods, const char *method)
571 * Returns 1 if the method completed any authentication list or 0 otherwise. 602 * Returns 1 if the method completed any authentication list or 0 otherwise.
572 */ 603 */
573int 604int
574auth2_update_methods_lists(Authctxt *authctxt, const char *method) 605auth2_update_methods_lists(Authctxt *authctxt, const char *method,
606 const char *submethod)
575{ 607{
576 u_int i, found = 0; 608 u_int i, found = 0;
577 609
578 debug3("%s: updating methods list after \"%s\"", __func__, method); 610 debug3("%s: updating methods list after \"%s\"", __func__, method);
579 for (i = 0; i < authctxt->num_auth_methods; i++) { 611 for (i = 0; i < authctxt->num_auth_methods; i++) {
580 if (!remove_method(&(authctxt->auth_methods[i]), method)) 612 if (!remove_method(&(authctxt->auth_methods[i]), method,
613 submethod))
581 continue; 614 continue;
582 found = 1; 615 found = 1;
583 if (*authctxt->auth_methods[i] == '\0') { 616 if (*authctxt->auth_methods[i] == '\0') {