--- /dev/null
+diff -up openssh-5.9p1/auth.h.2auth openssh-5.9p1/auth.h
+--- openssh-5.9p1/auth.h.2auth 2011-05-29 13:39:38.000000000 +0200
++++ openssh-5.9p1/auth.h 2011-09-17 11:36:54.314522599 +0200
+@@ -149,6 +149,8 @@ int auth_root_allowed(char *);
+
+ char *auth2_read_banner(void);
+
++void userauth_restart(const char *);
++
+ void privsep_challenge_enable(void);
+
+ int auth2_challenge(Authctxt *, char *);
+diff -up openssh-5.9p1/auth2.c.2auth openssh-5.9p1/auth2.c
+--- openssh-5.9p1/auth2.c.2auth 2011-05-05 06:04:11.000000000 +0200
++++ openssh-5.9p1/auth2.c 2011-09-17 11:36:54.402521709 +0200
+@@ -290,6 +290,24 @@ input_userauth_request(int type, u_int32
+ }
+
+ void
++userauth_restart(const char *method)
++{
++ options.two_factor_authentication = 0;
++
++ debug2("userauth restart, method = %s", method);
++ options.pubkey_authentication = options.second_pubkey_authentication && strcmp(method, method_pubkey.name);
++#ifdef GSSAPI
++ options.gss_authentication = options.second_gss_authentication && strcmp(method, method_gssapi.name);
++#endif
++#ifdef JPAKE
++ options.zero_knowledge_password_authentication = options.second_zero_knowledge_password_authentication && strcmp(method, method_jpake.name);
++#endif
++ options.password_authentication = options.second_password_authentication && strcmp(method, method_passwd.name);
++ options.kbd_interactive_authentication = options.second_kbd_interactive_authentication && strcmp(method, method_kbdint.name);
++ options.hostbased_authentication = options.second_hostbased_authentication && strcmp(method, method_hostbased.name);
++}
++
++void
+ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
+ {
+ char *methods;
+@@ -337,6 +355,12 @@ userauth_finish(Authctxt *authctxt, int
+
+ /* XXX todo: check if multiple auth methods are needed */
+ if (authenticated == 1) {
++ if (options.two_factor_authentication) {
++ userauth_restart(method);
++ debug("1st factor authentication done go to 2nd factor");
++ goto ask_methods;
++ }
++
+ /* turn off userauth */
+ dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
+ packet_start(SSH2_MSG_USERAUTH_SUCCESS);
+@@ -356,7 +380,9 @@ userauth_finish(Authctxt *authctxt, int
+ #endif
+ packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
+ }
++ask_methods:
+ methods = authmethods_get();
++ debug2("next auth methods = %s", methods);
+ packet_start(SSH2_MSG_USERAUTH_FAILURE);
+ packet_put_cstring(methods);
+ packet_put_char(0); /* XXX partial success, unused */
+diff -up openssh-5.9p1/monitor.c.2auth openssh-5.9p1/monitor.c
+--- openssh-5.9p1/monitor.c.2auth 2011-08-05 22:15:18.000000000 +0200
++++ openssh-5.9p1/monitor.c 2011-09-17 11:36:54.513491937 +0200
+@@ -417,6 +417,10 @@ monitor_child_preauth(Authctxt *_authctx
+ }
+ }
+ #endif
++ if (authenticated && options.two_factor_authentication) {
++ userauth_restart(auth_method);
++ authenticated = 0;
++ }
+ }
+
+ /* Drain any buffered messages from the child */
+diff -up openssh-5.9p1/servconf.c.2auth openssh-5.9p1/servconf.c
+--- openssh-5.9p1/servconf.c.2auth 2011-06-23 00:30:03.000000000 +0200
++++ openssh-5.9p1/servconf.c 2011-09-17 11:36:54.632461730 +0200
+@@ -92,6 +92,13 @@ initialize_server_options(ServerOptions
+ options->hostbased_uses_name_from_packet_only = -1;
+ options->rsa_authentication = -1;
+ options->pubkey_authentication = -1;
++ options->two_factor_authentication = -1;
++ options->second_pubkey_authentication = -1;
++ options->second_gss_authentication = -1;
++ options->second_password_authentication = -1;
++ options->second_kbd_interactive_authentication = -1;
++ options->second_zero_knowledge_password_authentication = -1;
++ options->second_hostbased_authentication = -1;
+ options->kerberos_authentication = -1;
+ options->kerberos_or_local_passwd = -1;
+ options->kerberos_ticket_cleanup = -1;
+@@ -237,6 +244,20 @@ fill_default_server_options(ServerOption
+ options->permit_empty_passwd = 0;
+ if (options->permit_user_env == -1)
+ options->permit_user_env = 0;
++ if (options->two_factor_authentication == -1)
++ options->two_factor_authentication = 0;
++ if (options->second_pubkey_authentication == -1)
++ options->second_pubkey_authentication = 1;
++ if (options->second_gss_authentication == -1)
++ options->second_gss_authentication = 0;
++ if (options->second_password_authentication == -1)
++ options->second_password_authentication = 1;
++ if (options->second_kbd_interactive_authentication == -1)
++ options->second_kbd_interactive_authentication = 0;
++ if (options->second_zero_knowledge_password_authentication == -1)
++ options->second_zero_knowledge_password_authentication = 0;
++ if (options->second_hostbased_authentication == -1)
++ options->second_hostbased_authentication = 0;
+ if (options->use_login == -1)
+ options->use_login = 0;
+ if (options->compression == -1)
+@@ -316,8 +337,11 @@ typedef enum {
+ sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
+ sMaxStartups, sMaxAuthTries, sMaxSessions,
+ sBanner, sUseDNS, sHostbasedAuthentication,
+- sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
+- sClientAliveCountMax, sAuthorizedKeysFile,
++ sHostbasedUsesNameFromPacketOnly, sTwoFactorAuthentication,
++ sSecondPubkeyAuthentication, sSecondGssAuthentication,
++ sSecondPasswordAuthentication, sSecondKbdInteractiveAuthentication,
++ sSecondZeroKnowledgePasswordAuthentication, sSecondHostbasedAuthentication,
++ sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
+ sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
+ sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
+ sUsePrivilegeSeparation, sAllowAgentForwarding,
+@@ -395,6 +419,21 @@ static struct {
+ #else
+ { "zeroknowledgepasswordauthentication", sUnsupported, SSHCFG_ALL },
+ #endif
++ { "twofactorauthentication", sTwoFactorAuthentication, SSHCFG_ALL },
++ { "secondpubkeyauthentication", sSecondPubkeyAuthentication, SSHCFG_ALL },
++#ifdef GSSAPI
++ { "secondgssapiauthentication", sSecondGssAuthentication, SSHCFG_ALL },
++#else
++ { "secondgssapiauthentication", sUnsupported, SSHCFG_ALL },
++#endif
++ { "secondpasswordauthentication", sSecondPasswordAuthentication, SSHCFG_ALL },
++ { "secondkbdinteractiveauthentication", sSecondKbdInteractiveAuthentication, SSHCFG_ALL },
++#ifdef JPAKE
++ { "secondzeroknowledgepasswordauthentication", sSecondZeroKnowledgePasswordAuthentication, SSHCFG_ALL },
++#else
++ { "secondzeroknowledgepasswordauthentication", sUnsupported, SSHCFG_ALL },
++#endif
++ { "secondhostbasedauthentication", sSecondHostbasedAuthentication, SSHCFG_ALL },
+ { "checkmail", sDeprecated, SSHCFG_GLOBAL },
+ { "listenaddress", sListenAddress, SSHCFG_GLOBAL },
+ { "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
+@@ -982,6 +1021,34 @@ process_server_config_line(ServerOptions
+ intptr = &options->challenge_response_authentication;
+ goto parse_flag;
+
++ case sTwoFactorAuthentication:
++ intptr = &options->two_factor_authentication;
++ goto parse_flag;
++
++ case sSecondPubkeyAuthentication:
++ intptr = &options->second_pubkey_authentication;
++ goto parse_flag;
++
++ case sSecondGssAuthentication:
++ intptr = &options->second_gss_authentication;
++ goto parse_flag;
++
++ case sSecondPasswordAuthentication:
++ intptr = &options->second_password_authentication;
++ goto parse_flag;
++
++ case sSecondKbdInteractiveAuthentication:
++ intptr = &options->second_kbd_interactive_authentication;
++ goto parse_flag;
++
++ case sSecondZeroKnowledgePasswordAuthentication:
++ intptr = &options->second_zero_knowledge_password_authentication;
++ goto parse_flag;
++
++ case sSecondHostbasedAuthentication:
++ intptr = &options->second_hostbased_authentication;
++ goto parse_flag;
++
+ case sPrintMotd:
+ intptr = &options->print_motd;
+ goto parse_flag;
+@@ -1491,14 +1558,21 @@ void
+ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
+ {
+ M_CP_INTOPT(password_authentication);
++ M_CP_INTOPT(second_password_authentication);
+ M_CP_INTOPT(gss_authentication);
++ M_CP_INTOPT(second_gss_authentication);
+ M_CP_INTOPT(rsa_authentication);
+ M_CP_INTOPT(pubkey_authentication);
++ M_CP_INTOPT(second_pubkey_authentication);
+ M_CP_INTOPT(kerberos_authentication);
+ M_CP_INTOPT(hostbased_authentication);
++ M_CP_INTOPT(second_hostbased_authentication);
+ M_CP_INTOPT(hostbased_uses_name_from_packet_only);
+ M_CP_INTOPT(kbd_interactive_authentication);
++ M_CP_INTOPT(second_kbd_interactive_authentication);
+ M_CP_INTOPT(zero_knowledge_password_authentication);
++ M_CP_INTOPT(second_zero_knowledge_password_authentication);
++ M_CP_INTOPT(two_factor_authentication);
+ M_CP_INTOPT(permit_root_login);
+ M_CP_INTOPT(permit_empty_passwd);
+
+@@ -1720,17 +1794,24 @@ dump_config(ServerOptions *o)
+ #endif
+ #ifdef GSSAPI
+ dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
++ dump_cfg_fmtint(sSecondGssAuthentication, o->second_gss_authentication);
+ dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
+ #endif
+ #ifdef JPAKE
+ dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication,
+ o->zero_knowledge_password_authentication);
++ dump_cfg_fmtint(sSecondZeroKnowledgePasswordAuthentication,
++ o->second_zero_knowledge_password_authentication);
+ #endif
+ dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
++ dump_cfg_fmtint(sSecondPasswordAuthentication, o->second_password_authentication);
+ dump_cfg_fmtint(sKbdInteractiveAuthentication,
+ o->kbd_interactive_authentication);
++ dump_cfg_fmtint(sSecondKbdInteractiveAuthentication,
++ o->second_kbd_interactive_authentication);
+ dump_cfg_fmtint(sChallengeResponseAuthentication,
+ o->challenge_response_authentication);
++ dump_cfg_fmtint(sTwoFactorAuthentication, o->two_factor_authentication);
+ dump_cfg_fmtint(sPrintMotd, o->print_motd);
+ dump_cfg_fmtint(sPrintLastLog, o->print_lastlog);
+ dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding);
+diff -up openssh-5.9p1/servconf.h.2auth openssh-5.9p1/servconf.h
+--- openssh-5.9p1/servconf.h.2auth 2011-06-23 00:30:03.000000000 +0200
++++ openssh-5.9p1/servconf.h 2011-09-17 11:36:54.749584245 +0200
+@@ -112,6 +112,14 @@ typedef struct {
+ /* If true, permit jpake auth */
+ int permit_empty_passwd; /* If false, do not permit empty
+ * passwords. */
++ int two_factor_authentication; /* If true, the first sucessful authentication
++ * will be followed by the second one from anorher set */
++ int second_pubkey_authentication; /* second set of authentications */
++ int second_gss_authentication;
++ int second_password_authentication;
++ int second_kbd_interactive_authentication;
++ int second_zero_knowledge_password_authentication;
++ int second_hostbased_authentication;
+ int permit_user_env; /* If true, read ~/.ssh/environment */
+ int use_login; /* If true, login(1) is used */
+ int compression; /* If true, compression is allowed */
+diff -up openssh-5.9p1/sshd_config.2auth openssh-5.9p1/sshd_config
+--- openssh-5.9p1/sshd_config.2auth 2011-05-29 13:39:39.000000000 +0200
++++ openssh-5.9p1/sshd_config 2011-09-17 11:36:54.859588726 +0200
+@@ -87,6 +87,13 @@ AuthorizedKeysFile .ssh/authorized_keys
+ # and ChallengeResponseAuthentication to 'no'.
+ #UsePAM no
+
++#TwoFactorAuthentication no
++#SecondPubkeyAuthentication yes
++#SecondHostbasedAuthentication no
++#SecondPasswordAuthentication yes
++#SecondKBDInteractiveAuthentication yes
++#SecondGSSAPIAuthentication no
++
+ #AllowAgentForwarding yes
+ #AllowTcpForwarding yes
+ #GatewayPorts no
+diff -up openssh-5.9p1/sshd_config.5.2auth openssh-5.9p1/sshd_config.5
+--- openssh-5.9p1/sshd_config.5.2auth 2011-08-05 22:17:33.000000000 +0200
++++ openssh-5.9p1/sshd_config.5 2011-09-17 13:45:49.022521436 +0200
+@@ -726,6 +726,12 @@ Available keywords are
+ .Cm PubkeyAuthentication ,
+ .Cm RhostsRSAAuthentication ,
+ .Cm RSAAuthentication ,
++.Cm SecondGSSAPIAuthentication ,
++.Cm SecondHostbasedAuthentication ,
++.Cm SecondKbdInteractiveAuthentication ,
++.Cm SecondPasswordAuthentication ,
++.Cm SecondPubkeyAuthentication ,
++.Cm TwoFactorAuthentication ,
+ .Cm X11DisplayOffset ,
+ .Cm X11Forwarding
+ and
+@@ -931,6 +937,45 @@ Specifies whether pure RSA authenticatio
+ The default is
+ .Dq yes .
+ This option applies to protocol version 1 only.
++.It Cm SecondGSSAPIAuthentication
++Specifies whether the
++.Cm GSSAPIAuthentication
++may be used on the second authentication while
++.Cm TwoFactorAuthentication
++is set.
++The default is
++.Dq no .
++.It Cm SecondHostbasedAuthentication
++Specifies whether the
++.Cm HostbasedAuthentication
++may be used on the second authentication while
++.Cm TwoFactorAuthentication
++is set.
++The default is
++.Dq no .
++.It Cm SecondKbdInteractiveAuthentication
++Specifies whether the
++.Cm KbdInteractiveAuthentication
++may be used on the second authentication while
++.Cm TwoFactorAuthentication
++is set.
++The default is
++.Dq yes .
++.It Cm SecondPasswordAuthentication
++Specifies whether the
++.Cm PasswordAuthentication
++may be used on the second authentication while
++.Cm TwoFactorAuthentication
++is set.
++The default is
++.Dq yes .
++Specifies whether the
++.Cm PubkeyAuthentication
++may be used on the second authentication while
++.Cm TwoFactorAuthentication
++is set.
++The default is
++.Dq yes .
+ .It Cm ServerKeyBits
+ Defines the number of bits in the ephemeral protocol version 1 server key.
+ The minimum value is 512, and the default is 1024.
+@@ -1011,6 +1056,23 @@ For more details on certificates, see th
+ .Sx CERTIFICATES
+ section in
+ .Xr ssh-keygen 1 .
++.It Cm TwoFactorAuthentication
++Specifies whether for a successful login is necessary to meet two independent authentications.
++If select the first method is selected from the set of allowed methods from
++.Cm GSSAPIAuthentication ,
++.Cm HostbasedAuthentication ,
++.Cm KbdInteractiveAuthentication ,
++.Cm PasswordAuthentication ,
++.Cm PubkeyAuthentication .
++And the second method is selected from the set of allowed methods from
++.Cm SecondGSSAPIAuthentication ,
++.Cm SecondHostbasedAuthentication ,
++.Cm SecondKbdInteractiveAuthentication ,
++.Cm SecondPasswordAuthentication ,
++.Cm SecondPubkeyAuthentication
++without the method used for the first authentication.
++The default is
++.Dq no .
+ .It Cm UseDNS
+ Specifies whether
+ .Xr sshd 8