diff options
author | djm@openbsd.org <djm@openbsd.org> | 2017-06-24 06:34:38 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2017-06-24 16:56:11 +1000 |
commit | 8f574959272ac7fe9239c4f5d10fd913f8920ab0 (patch) | |
tree | 51ab66a6011af6459e0d4ca15a4b4b78368607a1 /auth2.c | |
parent | e2004d4bb7eb01c663dd3a3e7eb224f1ccdc9bba (diff) |
upstream commit
refactor authentication logging
optionally record successful auth methods and public credentials
used in a file accessible to user sessions
feedback and ok markus@
Upstream-ID: 090b93036967015717b9a54fd0467875ae9d32fb
Diffstat (limited to 'auth2.c')
-rw-r--r-- | auth2.c | 133 |
1 files changed, 132 insertions, 1 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth2.c,v 1.142 2017/05/31 07:00:13 markus Exp $ */ | 1 | /* $OpenBSD: auth2.c,v 1.143 2017/06/24 06:34:38 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -30,6 +30,7 @@ | |||
30 | #include <sys/uio.h> | 30 | #include <sys/uio.h> |
31 | 31 | ||
32 | #include <fcntl.h> | 32 | #include <fcntl.h> |
33 | #include <limits.h> | ||
33 | #include <pwd.h> | 34 | #include <pwd.h> |
34 | #include <stdarg.h> | 35 | #include <stdarg.h> |
35 | #include <string.h> | 36 | #include <string.h> |
@@ -55,6 +56,7 @@ | |||
55 | #include "ssh-gss.h" | 56 | #include "ssh-gss.h" |
56 | #endif | 57 | #endif |
57 | #include "monitor_wrap.h" | 58 | #include "monitor_wrap.h" |
59 | #include "ssherr.h" | ||
58 | 60 | ||
59 | /* import */ | 61 | /* import */ |
60 | extern ServerOptions options; | 62 | extern ServerOptions options; |
@@ -277,6 +279,7 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) | |||
277 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); | 279 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); |
278 | #endif | 280 | #endif |
279 | 281 | ||
282 | auth2_authctxt_reset_info(authctxt); | ||
280 | authctxt->postponed = 0; | 283 | authctxt->postponed = 0; |
281 | authctxt->server_caused_failure = 0; | 284 | authctxt->server_caused_failure = 0; |
282 | 285 | ||
@@ -327,6 +330,10 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method, | |||
327 | /* Log before sending the reply */ | 330 | /* Log before sending the reply */ |
328 | auth_log(authctxt, authenticated, partial, method, submethod); | 331 | auth_log(authctxt, authenticated, partial, method, submethod); |
329 | 332 | ||
333 | /* Update information exposed to session */ | ||
334 | if (authenticated || partial) | ||
335 | auth2_update_session_info(authctxt, method, submethod); | ||
336 | |||
330 | if (authctxt->postponed) | 337 | if (authctxt->postponed) |
331 | return; | 338 | return; |
332 | 339 | ||
@@ -624,4 +631,128 @@ auth2_update_methods_lists(Authctxt *authctxt, const char *method, | |||
624 | return 0; | 631 | return 0; |
625 | } | 632 | } |
626 | 633 | ||
634 | /* Reset method-specific information */ | ||
635 | void auth2_authctxt_reset_info(Authctxt *authctxt) | ||
636 | { | ||
637 | sshkey_free(authctxt->auth_method_key); | ||
638 | free(authctxt->auth_method_info); | ||
639 | authctxt->auth_method_key = NULL; | ||
640 | authctxt->auth_method_info = NULL; | ||
641 | } | ||
642 | |||
643 | /* Record auth method-specific information for logs */ | ||
644 | void | ||
645 | auth2_record_info(Authctxt *authctxt, const char *fmt, ...) | ||
646 | { | ||
647 | va_list ap; | ||
648 | int i; | ||
649 | |||
650 | free(authctxt->auth_method_info); | ||
651 | authctxt->auth_method_info = NULL; | ||
652 | |||
653 | va_start(ap, fmt); | ||
654 | i = vasprintf(&authctxt->auth_method_info, fmt, ap); | ||
655 | va_end(ap); | ||
656 | |||
657 | if (i < 0 || authctxt->auth_method_info == NULL) | ||
658 | fatal("%s: vasprintf failed", __func__); | ||
659 | } | ||
660 | |||
661 | /* | ||
662 | * Records a public key used in authentication. This is used for logging | ||
663 | * and to ensure that the same key is not subsequently accepted again for | ||
664 | * multiple authentication. | ||
665 | */ | ||
666 | void | ||
667 | auth2_record_key(Authctxt *authctxt, int authenticated, | ||
668 | const struct sshkey *key) | ||
669 | { | ||
670 | struct sshkey **tmp, *dup; | ||
671 | int r; | ||
672 | |||
673 | if ((r = sshkey_demote(key, &dup)) != 0) | ||
674 | fatal("%s: copy key: %s", __func__, ssh_err(r)); | ||
675 | sshkey_free(authctxt->auth_method_key); | ||
676 | authctxt->auth_method_key = dup; | ||
677 | |||
678 | if (!authenticated) | ||
679 | return; | ||
680 | |||
681 | /* If authenticated, make sure we don't accept this key again */ | ||
682 | if ((r = sshkey_demote(key, &dup)) != 0) | ||
683 | fatal("%s: copy key: %s", __func__, ssh_err(r)); | ||
684 | if (authctxt->nprev_keys >= INT_MAX || | ||
685 | (tmp = recallocarray(authctxt->prev_keys, authctxt->nprev_keys, | ||
686 | authctxt->nprev_keys + 1, sizeof(*authctxt->prev_keys))) == NULL) | ||
687 | fatal("%s: reallocarray failed", __func__); | ||
688 | authctxt->prev_keys = tmp; | ||
689 | authctxt->prev_keys[authctxt->nprev_keys] = dup; | ||
690 | authctxt->nprev_keys++; | ||
691 | |||
692 | } | ||
693 | |||
694 | /* Checks whether a key has already been previously used for authentication */ | ||
695 | int | ||
696 | auth2_key_already_used(Authctxt *authctxt, const struct sshkey *key) | ||
697 | { | ||
698 | u_int i; | ||
699 | char *fp; | ||
700 | |||
701 | for (i = 0; i < authctxt->nprev_keys; i++) { | ||
702 | if (sshkey_equal_public(key, authctxt->prev_keys[i])) { | ||
703 | fp = sshkey_fingerprint(authctxt->prev_keys[i], | ||
704 | options.fingerprint_hash, SSH_FP_DEFAULT); | ||
705 | debug3("%s: key already used: %s %s", __func__, | ||
706 | sshkey_type(authctxt->prev_keys[i]), | ||
707 | fp == NULL ? "UNKNOWN" : fp); | ||
708 | free(fp); | ||
709 | return 1; | ||
710 | } | ||
711 | } | ||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | /* | ||
716 | * Updates authctxt->session_info with details of authentication. Should be | ||
717 | * whenever an authentication method succeeds. | ||
718 | */ | ||
719 | void | ||
720 | auth2_update_session_info(Authctxt *authctxt, const char *method, | ||
721 | const char *submethod) | ||
722 | { | ||
723 | int r; | ||
724 | |||
725 | if (authctxt->session_info == NULL) { | ||
726 | if ((authctxt->session_info = sshbuf_new()) == NULL) | ||
727 | fatal("%s: sshbuf_new", __func__); | ||
728 | } | ||
729 | |||
730 | /* Append method[/submethod] */ | ||
731 | if ((r = sshbuf_putf(authctxt->session_info, "%s%s%s", | ||
732 | method, submethod == NULL ? "" : "/", | ||
733 | submethod == NULL ? "" : submethod)) != 0) | ||
734 | fatal("%s: append method: %s", __func__, ssh_err(r)); | ||
735 | |||
736 | /* Append key if present */ | ||
737 | if (authctxt->auth_method_key != NULL) { | ||
738 | if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 || | ||
739 | (r = sshkey_format_text(authctxt->auth_method_key, | ||
740 | authctxt->session_info)) != 0) | ||
741 | fatal("%s: append key: %s", __func__, ssh_err(r)); | ||
742 | } | ||
743 | |||
744 | if (authctxt->auth_method_info != NULL) { | ||
745 | /* Ensure no ambiguity here */ | ||
746 | if (strchr(authctxt->auth_method_info, '\n') != NULL) | ||
747 | fatal("%s: auth_method_info contains \\n", __func__); | ||
748 | if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 || | ||
749 | (r = sshbuf_putf(authctxt->session_info, "%s", | ||
750 | authctxt->auth_method_info)) != 0) { | ||
751 | fatal("%s: append method info: %s", | ||
752 | __func__, ssh_err(r)); | ||
753 | } | ||
754 | } | ||
755 | if ((r = sshbuf_put_u8(authctxt->session_info, '\n')) != 0) | ||
756 | fatal("%s: append: %s", __func__, ssh_err(r)); | ||
757 | } | ||
627 | 758 | ||