version 1.142, 2017/05/31 07:00:13 |
version 1.143, 2017/06/24 06:34:38 |
|
|
#include <sys/uio.h> |
#include <sys/uio.h> |
|
|
#include <fcntl.h> |
#include <fcntl.h> |
|
#include <limits.h> |
#include <pwd.h> |
#include <pwd.h> |
#include <stdarg.h> |
#include <stdarg.h> |
#include <string.h> |
#include <string.h> |
|
|
#include "ssh-gss.h" |
#include "ssh-gss.h" |
#endif |
#endif |
#include "monitor_wrap.h" |
#include "monitor_wrap.h" |
|
#include "ssherr.h" |
|
|
/* import */ |
/* import */ |
extern ServerOptions options; |
extern ServerOptions options; |
|
|
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); |
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); |
#endif |
#endif |
|
|
|
auth2_authctxt_reset_info(authctxt); |
authctxt->postponed = 0; |
authctxt->postponed = 0; |
authctxt->server_caused_failure = 0; |
authctxt->server_caused_failure = 0; |
|
|
|
|
/* Log before sending the reply */ |
/* Log before sending the reply */ |
auth_log(authctxt, authenticated, partial, method, submethod); |
auth_log(authctxt, authenticated, partial, method, submethod); |
|
|
|
/* Update information exposed to session */ |
|
if (authenticated || partial) |
|
auth2_update_session_info(authctxt, method, submethod); |
|
|
if (authctxt->postponed) |
if (authctxt->postponed) |
return; |
return; |
|
|
|
|
return 0; |
return 0; |
} |
} |
|
|
|
/* Reset method-specific information */ |
|
void auth2_authctxt_reset_info(Authctxt *authctxt) |
|
{ |
|
sshkey_free(authctxt->auth_method_key); |
|
free(authctxt->auth_method_info); |
|
authctxt->auth_method_key = NULL; |
|
authctxt->auth_method_info = NULL; |
|
} |
|
|
|
/* Record auth method-specific information for logs */ |
|
void |
|
auth2_record_info(Authctxt *authctxt, const char *fmt, ...) |
|
{ |
|
va_list ap; |
|
int i; |
|
|
|
free(authctxt->auth_method_info); |
|
authctxt->auth_method_info = NULL; |
|
|
|
va_start(ap, fmt); |
|
i = vasprintf(&authctxt->auth_method_info, fmt, ap); |
|
va_end(ap); |
|
|
|
if (i < 0 || authctxt->auth_method_info == NULL) |
|
fatal("%s: vasprintf failed", __func__); |
|
} |
|
|
|
/* |
|
* Records a public key used in authentication. This is used for logging |
|
* and to ensure that the same key is not subsequently accepted again for |
|
* multiple authentication. |
|
*/ |
|
void |
|
auth2_record_key(Authctxt *authctxt, int authenticated, |
|
const struct sshkey *key) |
|
{ |
|
struct sshkey **tmp, *dup; |
|
int r; |
|
|
|
if ((r = sshkey_demote(key, &dup)) != 0) |
|
fatal("%s: copy key: %s", __func__, ssh_err(r)); |
|
sshkey_free(authctxt->auth_method_key); |
|
authctxt->auth_method_key = dup; |
|
|
|
if (!authenticated) |
|
return; |
|
|
|
/* If authenticated, make sure we don't accept this key again */ |
|
if ((r = sshkey_demote(key, &dup)) != 0) |
|
fatal("%s: copy key: %s", __func__, ssh_err(r)); |
|
if (authctxt->nprev_keys >= INT_MAX || |
|
(tmp = recallocarray(authctxt->prev_keys, authctxt->nprev_keys, |
|
authctxt->nprev_keys + 1, sizeof(*authctxt->prev_keys))) == NULL) |
|
fatal("%s: reallocarray failed", __func__); |
|
authctxt->prev_keys = tmp; |
|
authctxt->prev_keys[authctxt->nprev_keys] = dup; |
|
authctxt->nprev_keys++; |
|
|
|
} |
|
|
|
/* Checks whether a key has already been previously used for authentication */ |
|
int |
|
auth2_key_already_used(Authctxt *authctxt, const struct sshkey *key) |
|
{ |
|
u_int i; |
|
char *fp; |
|
|
|
for (i = 0; i < authctxt->nprev_keys; i++) { |
|
if (sshkey_equal_public(key, authctxt->prev_keys[i])) { |
|
fp = sshkey_fingerprint(authctxt->prev_keys[i], |
|
options.fingerprint_hash, SSH_FP_DEFAULT); |
|
debug3("%s: key already used: %s %s", __func__, |
|
sshkey_type(authctxt->prev_keys[i]), |
|
fp == NULL ? "UNKNOWN" : fp); |
|
free(fp); |
|
return 1; |
|
} |
|
} |
|
return 0; |
|
} |
|
|
|
/* |
|
* Updates authctxt->session_info with details of authentication. Should be |
|
* whenever an authentication method succeeds. |
|
*/ |
|
void |
|
auth2_update_session_info(Authctxt *authctxt, const char *method, |
|
const char *submethod) |
|
{ |
|
int r; |
|
|
|
if (authctxt->session_info == NULL) { |
|
if ((authctxt->session_info = sshbuf_new()) == NULL) |
|
fatal("%s: sshbuf_new", __func__); |
|
} |
|
|
|
/* Append method[/submethod] */ |
|
if ((r = sshbuf_putf(authctxt->session_info, "%s%s%s", |
|
method, submethod == NULL ? "" : "/", |
|
submethod == NULL ? "" : submethod)) != 0) |
|
fatal("%s: append method: %s", __func__, ssh_err(r)); |
|
|
|
/* Append key if present */ |
|
if (authctxt->auth_method_key != NULL) { |
|
if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 || |
|
(r = sshkey_format_text(authctxt->auth_method_key, |
|
authctxt->session_info)) != 0) |
|
fatal("%s: append key: %s", __func__, ssh_err(r)); |
|
} |
|
|
|
if (authctxt->auth_method_info != NULL) { |
|
/* Ensure no ambiguity here */ |
|
if (strchr(authctxt->auth_method_info, '\n') != NULL) |
|
fatal("%s: auth_method_info contains \\n", __func__); |
|
if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 || |
|
(r = sshbuf_putf(authctxt->session_info, "%s", |
|
authctxt->auth_method_info)) != 0) { |
|
fatal("%s: append method info: %s", |
|
__func__, ssh_err(r)); |
|
} |
|
} |
|
if ((r = sshbuf_put_u8(authctxt->session_info, '\n')) != 0) |
|
fatal("%s: append: %s", __func__, ssh_err(r)); |
|
} |
|
|