update version
[openssh.git] / auth2.c
diff --git a/auth2.c b/auth2.c
index 52acf46..50f1352 100644 (file)
--- a/auth2.c
+++ b/auth2.c
@@ -223,10 +223,30 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
        if (authctxt == NULL)
                fatal("input_userauth_request: no authctxt");
 
-       user = packet_get_cstring(NULL);
-       service = packet_get_cstring(NULL);
-       method = packet_get_cstring(NULL);
-       debug("userauth-request for user %s service %s method %s", user, service, method);
+       user = packet_get_string(NULL);
+       service = packet_get_string(NULL);
+       method = packet_get_string(NULL);
+
+#ifdef GSSAPI
+       if (user[0] == '\0') {
+           debug("received empty username for %s", method);
+           if (strcmp(method, "gssapi-keyex") == 0) {
+               char *lname = NULL;
+               PRIVSEP(ssh_gssapi_localname(&lname));
+               if (lname && lname[0] != '\0') {
+                   xfree(user);
+                   user = lname;
+                   debug("set username to %s from gssapi context", user);
+               } else {
+                   debug("failed to set username from gssapi context");
+                   packet_send_debug("failed to set username from gssapi context");
+               }
+           }
+       }
+#endif
+
+       debug("userauth-request for user %s service %s method %s",
+             user[0] ? user : "<implicit>", service, method);
        debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
 
        if ((role = strchr(user, '/')) != NULL)
@@ -237,11 +257,32 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
        else if (role && (style = strchr(role, ':')) != 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") == 0) ||
+                    (strcmp(method, "gssapi-with-mic") == 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 {
@@ -251,21 +292,26 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
                        PRIVSEP(audit_event(SSH_INVALID_USER));
 #endif
                }
+#ifdef GSSAPI
+               } /* endif for setting username based on GSSAPI context */
+#endif
 #ifdef USE_PAM
                if (options.use_pam)
                        PRIVSEP(start_pam(authctxt));
 #endif
                setproctitle("%s%s", authctxt->valid ? user : "unknown",
                    use_privsep ? " [net]" : "");
-               authctxt->service = xstrdup(service);
-               authctxt->style = style ? xstrdup(style) : NULL;
-               authctxt->role = role ? xstrdup(role) : NULL;
-               if (use_privsep)
-                       mm_inform_authserv(service, style, role);
-               userauth_banner();
-       } else if (strcmp(user, authctxt->user) != 0 ||
-           strcmp(service, authctxt->service) != 0) {
-               packet_disconnect("Change of username or service not allowed: "
+               if (authctxt->attempt == 1) {
+            authctxt->service = xstrdup(service);
+            authctxt->style = style ? xstrdup(style) : NULL;
+           authctxt->role = role ? xstrdup(role) : NULL;
+            if (use_privsep)
+             mm_inform_authserv(service, style, role);
+            userauth_banner();
+               }
+       }
+       if (strcmp(service, authctxt->service) != 0) {
+               packet_disconnect("Change of service not allowed: "
                    "(%s,%s) -> (%s,%s)",
                    authctxt->user, authctxt->service, user, service);
        }