extern Authmethod method_kbdint;
extern Authmethod method_hostbased;
#ifdef GSSAPI
+extern Authmethod method_gsskeyex;
extern Authmethod method_gssapi;
#endif
#ifdef JPAKE
&method_none,
&method_pubkey,
#ifdef GSSAPI
+ &method_gsskeyex,
&method_gssapi,
#endif
#ifdef JPAKE
if ((style = strchr(user, ':')) != NULL)
*style++ = 0;
- if (authctxt->attempt++ == 0) {
- /* setup auth context */
+ /* If first time or username changed or empty username,
+ setup/reset authentication context. */
+ if ((authctxt->attempt++ == 0) ||
+ (strcmp(user, authctxt->user) != 0) ||
+ (strcmp(user, "") == 0)) {
+ if (authctxt->user) {
+ xfree(authctxt->user);
+ authctxt->user = NULL;
+ }
+ authctxt->valid = 0;
+ authctxt->user = xstrdup(user);
+ if (strcmp(service, "ssh-connection") != 0) {
+ packet_disconnect("Unsupported service %s", service);
+ }
+#ifdef GSSAPI
+ /* If we're going to set the username based on the
+ GSSAPI context later, then wait until then to
+ verify it. Just put in placeholders for now. */
+ if ((strcmp(user, "") == 0) &&
+ (strcmp(method, "gssapi-with-mic") == 0 ||
+ strcmp(method, "gssapi-keyex") == 0)) {
+ authctxt->pw = fakepw();
+ } else {
+#endif
authctxt->pw = PRIVSEP(getpwnamallow(user));
- authctxt->user = xstrdup(user);
- if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
+ if (authctxt->pw) {
authctxt->valid = 1;
debug2("input_userauth_request: setting up authctxt for %s", user);
} else {
if (options.use_pam)
PRIVSEP(start_pam(authctxt));
#endif
+#ifdef GSSAPI
+ } /* endif for setting username based on GSSAPI context */
+#endif
setproctitle("%s%s", authctxt->valid ? user : "unknown",
use_privsep ? " [net]" : "");
- authctxt->service = xstrdup(service);
- authctxt->style = style ? xstrdup(style) : NULL;
- if (use_privsep)
- mm_inform_authserv(service, style);
- userauth_banner();
- } else if (strcmp(user, authctxt->user) != 0 ||
- strcmp(service, authctxt->service) != 0) {
+ if (authctxt->attempt == 1) {
+ authctxt->service = xstrdup(service);
+ authctxt->style = style ? xstrdup(style) : NULL;
+ if (use_privsep)
+ mm_inform_authserv(service, style);
+ userauth_banner();
+ }
+ }
+ if (strcmp(service, authctxt->service) != 0) {
packet_disconnect("Change of username or service not allowed: "
"(%s,%s) -> (%s,%s)",
authctxt->user, authctxt->service, user, service);
#endif
authctxt->postponed = 0;
+ authctxt->server_caused_failure = 0;
/* try to authenticate user */
m = authmethod_lookup(method);
} else {
/* Allow initial try of "none" auth without failure penalty */
- if (authctxt->attempt > 1 || strcmp(method, "none") != 0)
+ if (!authctxt->server_caused_failure &&
+ (authctxt->attempt > 1 || strcmp(method, "none") != 0))
authctxt->failures++;
if (authctxt->failures >= options.max_authtries) {
#ifdef SSH_AUDIT_EVENTS