diff --git a/openssh-5.8p2-askpass-ld.patch b/openssh-5.8p2-askpass-ld.patch deleted file mode 100644 index 5b85c80..0000000 --- a/openssh-5.8p2-askpass-ld.patch +++ /dev/null @@ -1,18 +0,0 @@ -diff -up openssh-5.8p2/contrib/Makefile.askpass-ld openssh-5.8p2/contrib/Makefile ---- openssh-5.8p2/contrib/Makefile.askpass-ld 2011-08-08 22:54:06.050546199 +0200 -+++ openssh-5.8p2/contrib/Makefile 2011-08-08 22:54:43.364420118 +0200 -@@ -2,12 +2,12 @@ all: - @echo "Valid targets: gnome-ssh-askpass1 gnome-ssh-askpass2" - - gnome-ssh-askpass1: gnome-ssh-askpass1.c -- $(CC) `gnome-config --cflags gnome gnomeui` \ -+ $(CC) ${CFLAGS} `gnome-config --cflags gnome gnomeui` \ - gnome-ssh-askpass1.c -o gnome-ssh-askpass1 \ - `gnome-config --libs gnome gnomeui` - - gnome-ssh-askpass2: gnome-ssh-askpass2.c -- $(CC) `pkg-config --cflags gtk+-2.0` \ -+ $(CC) ${CFLAGS} `pkg-config --cflags gtk+-2.0` \ - gnome-ssh-askpass2.c -o gnome-ssh-askpass2 \ - `pkg-config --libs gtk+-2.0 x11` - diff --git a/openssh-5.9p1-akc.patch b/openssh-5.9p1-akc.patch deleted file mode 100644 index e50098f..0000000 --- a/openssh-5.9p1-akc.patch +++ /dev/null @@ -1,451 +0,0 @@ -diff -up openssh-5.9p1/auth2-pubkey.c.akc openssh-5.9p1/auth2-pubkey.c ---- openssh-5.9p1/auth2-pubkey.c.akc 2012-02-06 20:47:36.641814218 +0100 -+++ openssh-5.9p1/auth2-pubkey.c 2012-02-06 20:47:36.665095838 +0100 -@@ -27,6 +27,7 @@ - - #include - #include -+#include - - #include - #include -@@ -276,27 +277,15 @@ match_principals_file(char *file, struct - - /* return 1 if user allows given key */ - static int --user_key_allowed2(struct passwd *pw, Key *key, char *file) -+user_search_key_in_file(FILE *f, char *file, Key* key, struct passwd *pw) - { - char line[SSH_MAX_PUBKEY_BYTES]; - const char *reason; - int found_key = 0; -- FILE *f; - u_long linenum = 0; - Key *found; - char *fp; - -- /* Temporarily use the user's uid. */ -- temporarily_use_uid(pw); -- -- debug("trying public key file %s", file); -- f = auth_openkeyfile(file, pw, options.strict_modes); -- -- if (!f) { -- restore_uid(); -- return 0; -- } -- - found_key = 0; - found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type); - -@@ -389,8 +378,6 @@ user_key_allowed2(struct passwd *pw, Key - break; - } - } -- restore_uid(); -- fclose(f); - key_free(found); - if (!found_key) - debug2("key not found"); -@@ -452,13 +439,191 @@ user_cert_trusted_ca(struct passwd *pw, - return ret; - } - --/* check whether given key is in .ssh/authorized_keys* */ -+/* return 1 if user allows given key */ -+static int -+user_key_allowed2(struct passwd *pw, Key *key, char *file) -+{ -+ FILE *f; -+ int found_key = 0; -+ -+ /* Temporarily use the user's uid. */ -+ temporarily_use_uid(pw); -+ -+ debug("trying public key file %s", file); -+ f = auth_openkeyfile(file, pw, options.strict_modes); -+ -+ if (f) { -+ found_key = user_search_key_in_file (f, file, key, pw); -+ fclose(f); -+ } -+ -+ restore_uid(); -+ return found_key; -+} -+ -+#ifdef WITH_AUTHORIZED_KEYS_COMMAND -+ -+#define WHITESPACE " \t\r\n" -+ -+/* return 1 if user allows given key */ -+static int -+user_key_via_command_allowed2(struct passwd *pw, Key *key) -+{ -+ FILE *f; -+ int found_key = 0; -+ char *progname = NULL; -+ char *cp; -+ struct passwd *runas_pw; -+ struct stat st; -+ int childdescriptors[2], i; -+ pid_t pstat, pid, child; -+ -+ if (options.authorized_keys_command == NULL || options.authorized_keys_command[0] != '/') -+ return 0; -+ -+ /* get the run as identity from config */ -+ runas_pw = (options.authorized_keys_command_runas == NULL)? pw -+ : getpwnam (options.authorized_keys_command_runas); -+ if (!runas_pw) { -+ error("%s: getpwnam(\"%s\"): %s", __func__, -+ options.authorized_keys_command_runas, strerror(errno)); -+ return 0; -+ } -+ -+ /* Temporarily use the specified uid. */ -+ if (runas_pw->pw_uid != 0) -+ temporarily_use_uid(runas_pw); -+ -+ progname = xstrdup(options.authorized_keys_command); -+ -+ debug3("%s: checking program '%s'", __func__, progname); -+ -+ if (stat (progname, &st) < 0) { -+ error("%s: stat(\"%s\"): %s", __func__, -+ progname, strerror(errno)); -+ goto go_away; -+ } -+ -+ if (st.st_uid != 0 || (st.st_mode & 022) != 0) { -+ error("bad ownership or modes for AuthorizedKeysCommand \"%s\"", -+ progname); -+ goto go_away; -+ } -+ -+ if (!S_ISREG(st.st_mode)) { -+ error("AuthorizedKeysCommand \"%s\" is not a regular file", -+ progname); -+ goto go_away; -+ } -+ -+ /* -+ * Descend the path, checking that each component is a -+ * root-owned directory with strict permissions. -+ */ -+ do { -+ if ((cp = strrchr(progname, '/')) == NULL) -+ break; -+ else -+ *cp = '\0'; -+ -+ debug3("%s: checking component '%s'", __func__, (*progname == '\0' ? "/" : progname)); -+ -+ if (stat((*progname == '\0' ? "/" : progname), &st) != 0) { -+ error("%s: stat(\"%s\"): %s", __func__, -+ progname, strerror(errno)); -+ goto go_away; -+ } -+ if (st.st_uid != 0 || (st.st_mode & 022) != 0) { -+ error("bad ownership or modes for AuthorizedKeysCommand path component \"%s\"", -+ progname); -+ goto go_away; -+ } -+ if (!S_ISDIR(st.st_mode)) { -+ error("AuthorizedKeysCommand path component \"%s\" is not a directory", -+ progname); -+ goto go_away; -+ } -+ } while (1); -+ -+ /* open the pipe and read the keys */ -+ if (pipe(childdescriptors)) { -+ error("failed to pipe(2) for AuthorizedKeysCommand: %s", -+ strerror(errno)); -+ goto go_away; -+ } -+ -+ child = fork(); -+ if (child == -1) { -+ error("failed to fork(2) for AuthorizedKeysCommand: %s", -+ strerror(errno)); -+ goto go_away; -+ } else if (child == 0) { -+ /* we're in the child process here -- we should never return from this block. */ -+ /* permanently drop privs in child process */ -+ if (runas_pw->pw_uid != 0) { -+ restore_uid(); -+ permanently_set_uid(runas_pw); -+ } -+ -+ close(childdescriptors[0]); -+ /* put the write end of the pipe on stdout (FD 1) */ -+ if (dup2(childdescriptors[1], 1) == -1) { -+ error("failed to dup2(2) from AuthorizedKeysCommand: %s", -+ strerror(errno)); -+ _exit(127); -+ } -+ -+ debug3("about to execl() AuthorizedKeysCommand: \"%s\" \"%s\"", options.authorized_keys_command, pw->pw_name); -+ /* see session.c:child_close_fds() */ -+ for (i = 3; i < 64; ++i) { -+ close(i); -+ } -+ -+ execl(options.authorized_keys_command, options.authorized_keys_command, pw->pw_name, NULL); -+ -+ /* if we got here, it didn't work */ -+ error("failed to execl AuthorizedKeysCommand: %s", strerror(errno)); /* this won't work because we closed the fds above */ -+ _exit(127); -+ } -+ -+ close(childdescriptors[1]); -+ f = fdopen(childdescriptors[0], "r"); -+ if (!f) { -+ error("%s: could not buffer FDs from AuthorizedKeysCommand (\"%s\", \"r\"): %s", __func__, -+ options.authorized_keys_command, strerror (errno)); -+ goto go_away; -+ } -+ -+ found_key = user_search_key_in_file (f, options.authorized_keys_command, key, pw); -+ fclose (f); -+ do { -+ pid = waitpid(child, &pstat, 0); -+ } while (pid == -1 && errno == EINTR); -+ -+ /* what about the return value from the child process? */ -+go_away: -+ if (progname) -+ xfree (progname); -+ -+ if (runas_pw->pw_uid != 0) -+ restore_uid(); -+ return found_key; -+} -+#endif -+ -+/* check whether given key is in 0) -+ return success; -+#endif -+ - if (auth_key_is_revoked(key)) - return 0; - if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key)) -diff -up openssh-5.9p1/configure.ac.akc openssh-5.9p1/configure.ac ---- openssh-5.9p1/configure.ac.akc 2012-02-06 20:47:36.656046570 +0100 -+++ openssh-5.9p1/configure.ac 2012-02-06 20:47:36.666095176 +0100 -@@ -1421,6 +1421,18 @@ AC_ARG_WITH([audit], - esac ] - ) - -+# Check whether user wants AuthorizedKeysCommand support -+AKC_MSG="no" -+AC_ARG_WITH(authorized-keys-command, -+ [ --with-authorized-keys-command Enable AuthorizedKeysCommand support], -+ [ -+ if test "x$withval" != "xno" ; then -+ AC_DEFINE([WITH_AUTHORIZED_KEYS_COMMAND], 1, [Enable AuthorizedKeysCommand support]) -+ AKC_MSG="yes" -+ fi -+ ] -+) -+ - dnl Checks for library functions. Please keep in alphabetical order - AC_CHECK_FUNCS([ \ - arc4random \ -@@ -4239,6 +4251,7 @@ echo " SELinux support - echo " Smartcard support: $SCARD_MSG" - echo " S/KEY support: $SKEY_MSG" - echo " TCP Wrappers support: $TCPW_MSG" -+echo " AuthorizedKeysCommand support: $AKC_MSG" - echo " MD5 password support: $MD5_MSG" - echo " libedit support: $LIBEDIT_MSG" - echo " Solaris process contract support: $SPC_MSG" -diff -up openssh-5.9p1/servconf.c.akc openssh-5.9p1/servconf.c ---- openssh-5.9p1/servconf.c.akc 2012-02-06 20:47:36.573033521 +0100 -+++ openssh-5.9p1/servconf.c 2012-02-06 20:47:36.667106367 +0100 -@@ -136,6 +136,8 @@ initialize_server_options(ServerOptions - options->num_permitted_opens = -1; - options->adm_forced_command = NULL; - options->chroot_directory = NULL; -+ options->authorized_keys_command = NULL; -+ options->authorized_keys_command_runas = NULL; - options->zero_knowledge_password_authentication = -1; - options->revoked_keys_file = NULL; - options->trusted_user_ca_keys = NULL; -@@ -329,6 +331,7 @@ typedef enum { - sZeroKnowledgePasswordAuthentication, sHostCertificate, - sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, - sKexAlgorithms, sIPQoS, -+ sAuthorizedKeysCommand, sAuthorizedKeysCommandRunAs, - sDeprecated, sUnsupported - } ServerOpCodes; - -@@ -455,6 +458,13 @@ static struct { - { "requiredauthentications1", sRequiredAuthentications1, SSHCFG_ALL }, - { "requiredauthentications2", sRequiredAuthentications2, SSHCFG_ALL }, - { "ipqos", sIPQoS, SSHCFG_ALL }, -+#ifdef WITH_AUTHORIZED_KEYS_COMMAND -+ { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, -+ { "authorizedkeyscommandrunas", sAuthorizedKeysCommandRunAs, SSHCFG_ALL }, -+#else -+ { "authorizedkeyscommand", sUnsupported, SSHCFG_ALL }, -+ { "authorizedkeyscommandrunas", sUnsupported, SSHCFG_ALL }, -+#endif - { NULL, sBadOption, 0 } - }; - -@@ -1430,6 +1440,24 @@ process_server_config_line(ServerOptions - } - break; - -+ case sAuthorizedKeysCommand: -+ len = strspn(cp, WHITESPACE); -+ if (*activep && options->authorized_keys_command == NULL) -+ options->authorized_keys_command = xstrdup(cp + len); -+ return 0; -+ -+ case sAuthorizedKeysCommandRunAs: -+ charptr = &options->authorized_keys_command_runas; -+ -+ arg = strdelim(&cp); -+ if (!arg || *arg == '\0') -+ fatal("%s line %d: missing account.", -+ filename, linenum); -+ -+ if (*activep && *charptr == NULL) -+ *charptr = xstrdup(arg); -+ break; -+ - case sDeprecated: - logit("%s line %d: Deprecated option %s", - filename, linenum, arg); -@@ -1534,6 +1562,8 @@ copy_set_server_options(ServerOptions *d - M_CP_INTOPT(hostbased_uses_name_from_packet_only); - M_CP_INTOPT(kbd_interactive_authentication); - M_CP_INTOPT(zero_knowledge_password_authentication); -+ M_CP_STROPT(authorized_keys_command); -+ M_CP_STROPT(authorized_keys_command_runas); - M_CP_INTOPT(permit_root_login); - M_CP_INTOPT(permit_empty_passwd); - -@@ -1793,6 +1823,8 @@ dump_config(ServerOptions *o) - dump_cfg_string(sRevokedKeys, o->revoked_keys_file); - dump_cfg_string(sAuthorizedPrincipalsFile, - o->authorized_principals_file); -+ dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command); -+ dump_cfg_string(sAuthorizedKeysCommandRunAs, o->authorized_keys_command_runas); - - /* string arguments requiring a lookup */ - dump_cfg_string(sLogLevel, log_level_name(o->log_level)); -diff -up openssh-5.9p1/servconf.h.akc openssh-5.9p1/servconf.h ---- openssh-5.9p1/servconf.h.akc 2012-02-06 20:47:36.574033734 +0100 -+++ openssh-5.9p1/servconf.h 2012-02-06 20:47:36.668096740 +0100 -@@ -169,6 +169,8 @@ typedef struct { - char *revoked_keys_file; - char *trusted_user_ca_keys; - char *authorized_principals_file; -+ char *authorized_keys_command; -+ char *authorized_keys_command_runas; - } ServerOptions; - - /* -diff -up openssh-5.9p1/sshd_config.akc openssh-5.9p1/sshd_config ---- openssh-5.9p1/sshd_config.akc 2011-05-29 13:39:39.000000000 +0200 -+++ openssh-5.9p1/sshd_config 2012-02-06 20:47:36.669067546 +0100 -@@ -49,6 +49,9 @@ - # but this is overridden so installations will only check .ssh/authorized_keys - AuthorizedKeysFile .ssh/authorized_keys - -+#AuthorizedKeysCommand none -+#AuthorizedKeysCommandRunAs nobody -+ - # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts - #RhostsRSAAuthentication no - # similar for protocol version 2 -diff -up openssh-5.9p1/sshd_config.0.akc openssh-5.9p1/sshd_config.0 ---- openssh-5.9p1/sshd_config.0.akc 2011-09-07 01:16:30.000000000 +0200 -+++ openssh-5.9p1/sshd_config.0 2012-02-06 20:47:36.669067546 +0100 -@@ -71,6 +71,23 @@ DESCRIPTION - - See PATTERNS in ssh_config(5) for more information on patterns. - -+ AuthorizedKeysCommand -+ -+ Specifies a program to be used for lookup of the user's -+ public keys. The program will be invoked with its first -+ argument the name of the user being authorized, and should produce -+ on standard output AuthorizedKeys lines (see AUTHORIZED_KEYS -+ in sshd(8)). By default (or when set to the empty string) there is no -+ AuthorizedKeysCommand run. If the AuthorizedKeysCommand does not successfully -+ authorize the user, authorization falls through to the -+ AuthorizedKeysFile. Note that this option has an effect -+ only with PubkeyAuthentication turned on. -+ -+ AuthorizedKeysCommandRunAs -+ Specifies the user under whose account the AuthorizedKeysCommand is run. -+ Empty string (the default value) means the user being authorized -+ is used. -+ - AuthorizedKeysFile - Specifies the file that contains the public keys that can be used - for user authentication. The format is described in the -@@ -401,7 +418,8 @@ DESCRIPTION - - Only a subset of keywords may be used on the lines following a - Match keyword. Available keywords are AllowAgentForwarding, -- AllowTcpForwarding, AuthorizedKeysFile, AuthorizedPrincipalsFile, -+ AllowTcpForwarding, AuthorizedKeysFile, AuthorizedKeysCommand, -+ AuthorizedKeysCommandRunAs, AuthorizedPrincipalsFile, - Banner, ChrootDirectory, ForceCommand, GatewayPorts, - GSSAPIAuthentication, HostbasedAuthentication, - HostbasedUsesNameFromPacketOnly, KbdInteractiveAuthentication, -diff -up openssh-5.9p1/sshd_config.5.akc openssh-5.9p1/sshd_config.5 ---- openssh-5.9p1/sshd_config.5.akc 2012-02-06 20:47:36.574891218 +0100 -+++ openssh-5.9p1/sshd_config.5 2012-02-06 20:49:58.913878595 +0100 -@@ -151,6 +151,19 @@ See - in - .Xr ssh_config 5 - for more information on patterns. -+.It Cm AuthorizedKeysCommand -+Specifies a program to be used for lookup of the user's -+public keys. The program will be invoked with its first -+argument the name of the user being authorized, and should produce -+on standard output AuthorizedKeys lines (see AUTHORIZED_KEYS -+in sshd(8)). By default (or when set to the empty string) there is no -+AuthorizedKeysCommand run. If the AuthorizedKeysCommand does not successfully -+authorize the user, authorization falls through to the -+AuthorizedKeysFile. Note that this option has an effect -+only with PubkeyAuthentication turned on. -+.It Cm AuthorizedKeysCommandRunAs -+Specifies the user under whose account the AuthorizedKeysCommand is run. Empty -+string (the default value) means the user being authorized is used. - .It Cm AuthorizedKeysFile - Specifies the file that contains the public keys that can be used - for user authentication. -@@ -706,6 +719,8 @@ Available keywords are - .Cm AllowAgentForwarding , - .Cm AllowTcpForwarding , - .Cm AuthorizedKeysFile , -+.Cm AuthorizedKeysCommand , -+.Cm AuthorizedKeysCommandRunAs , - .Cm AuthorizedPrincipalsFile , - .Cm Banner , - .Cm ChrootDirectory , -@@ -718,6 +733,7 @@ Available keywords are - .Cm KerberosAuthentication , - .Cm MaxAuthTries , - .Cm MaxSessions , -+.Cm PubkeyAuthentication , - .Cm PasswordAuthentication , - .Cm PermitEmptyPasswords , - .Cm PermitOpen , diff --git a/openssh-5.9p1-coverity.patch b/openssh-5.9p1-coverity.patch deleted file mode 100644 index f3524e3..0000000 --- a/openssh-5.9p1-coverity.patch +++ /dev/null @@ -1,844 +0,0 @@ -diff -up openssh-5.9p1/auth-pam.c.coverity openssh-5.9p1/auth-pam.c ---- openssh-5.9p1/auth-pam.c.coverity 2009-07-12 14:07:21.000000000 +0200 -+++ openssh-5.9p1/auth-pam.c 2011-09-14 08:09:47.074520582 +0200 -@@ -216,7 +216,12 @@ pthread_join(sp_pthread_t thread, void * - if (sshpam_thread_status != -1) - return (sshpam_thread_status); - signal(SIGCHLD, sshpam_oldsig); -- waitpid(thread, &status, 0); -+ while (waitpid(thread, &status, 0) < 0) { -+ if (errno == EINTR) -+ continue; -+ fatal("%s: waitpid: %s", __func__, -+ strerror(errno)); -+ } - return (status); - } - #endif -diff -up openssh-5.9p1/channels.c.coverity openssh-5.9p1/channels.c ---- openssh-5.9p1/channels.c.coverity 2011-06-23 00:31:57.000000000 +0200 -+++ openssh-5.9p1/channels.c 2011-09-14 08:09:47.556582810 +0200 -@@ -229,11 +229,11 @@ channel_register_fds(Channel *c, int rfd - channel_max_fd = MAX(channel_max_fd, wfd); - channel_max_fd = MAX(channel_max_fd, efd); - -- if (rfd != -1) -+ if (rfd >= 0) - fcntl(rfd, F_SETFD, FD_CLOEXEC); -- if (wfd != -1 && wfd != rfd) -+ if (wfd >= 0 && wfd != rfd) - fcntl(wfd, F_SETFD, FD_CLOEXEC); -- if (efd != -1 && efd != rfd && efd != wfd) -+ if (efd >= 0 && efd != rfd && efd != wfd) - fcntl(efd, F_SETFD, FD_CLOEXEC); - - c->rfd = rfd; -@@ -248,11 +248,11 @@ channel_register_fds(Channel *c, int rfd - - /* enable nonblocking mode */ - if (nonblock) { -- if (rfd != -1) -+ if (rfd >= 0) - set_nonblock(rfd); -- if (wfd != -1) -+ if (wfd >= 0) - set_nonblock(wfd); -- if (efd != -1) -+ if (efd >= 0) - set_nonblock(efd); - } - } -diff -up openssh-5.9p1/clientloop.c.coverity openssh-5.9p1/clientloop.c ---- openssh-5.9p1/clientloop.c.coverity 2011-06-23 00:31:58.000000000 +0200 -+++ openssh-5.9p1/clientloop.c 2011-09-14 08:17:41.556521887 +0200 -@@ -1970,14 +1970,15 @@ client_input_global_request(int type, u_ - char *rtype; - int want_reply; - int success = 0; -+/* success is still 0 the packet is allways SSH2_MSG_REQUEST_FAILURE, isn't it? */ - - rtype = packet_get_string(NULL); - want_reply = packet_get_char(); - debug("client_input_global_request: rtype %s want_reply %d", - rtype, want_reply); - if (want_reply) { -- packet_start(success ? -- SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); -+ packet_start(/*success ? -+ SSH2_MSG_REQUEST_SUCCESS :*/ SSH2_MSG_REQUEST_FAILURE); - packet_send(); - packet_write_wait(); - } -diff -up openssh-5.9p1/key.c.coverity openssh-5.9p1/key.c ---- openssh-5.9p1/key.c.coverity 2011-05-20 11:03:08.000000000 +0200 -+++ openssh-5.9p1/key.c 2011-09-14 08:09:47.803458435 +0200 -@@ -803,8 +803,10 @@ key_read(Key *ret, char **cpp) - success = 1; - /*XXXX*/ - key_free(k); -+/*XXXX - if (success != 1) - break; -+XXXX*/ - /* advance cp: skip whitespace and data */ - while (*cp == ' ' || *cp == '\t') - cp++; -diff -up openssh-5.9p1/misc.c.coverity openssh-5.9p1/misc.c -diff -up openssh-5.9p1/monitor.c.coverity openssh-5.9p1/monitor.c ---- openssh-5.9p1/monitor.c.coverity 2011-08-05 22:15:18.000000000 +0200 -+++ openssh-5.9p1/monitor.c 2011-09-14 08:09:47.914584009 +0200 -@@ -420,7 +420,7 @@ monitor_child_preauth(Authctxt *_authctx - } - - /* Drain any buffered messages from the child */ -- while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) -+ while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0) - ; - - if (!authctxt->valid) -@@ -1161,6 +1161,10 @@ mm_answer_keyallowed(int sock, Buffer *m - break; - } - } -+ -+ debug3("%s: key %p is %s", -+ __func__, key, allowed ? "allowed" : "not allowed"); -+ - if (key != NULL) - key_free(key); - -@@ -1182,9 +1186,6 @@ mm_answer_keyallowed(int sock, Buffer *m - xfree(chost); - } - -- debug3("%s: key %p is %s", -- __func__, key, allowed ? "allowed" : "not allowed"); -- - buffer_clear(m); - buffer_put_int(m, allowed); - buffer_put_int(m, forced_command != NULL); -diff -up openssh-5.9p1/monitor_wrap.c.coverity openssh-5.9p1/monitor_wrap.c ---- openssh-5.9p1/monitor_wrap.c.coverity 2011-09-14 08:11:36.480500123 +0200 -+++ openssh-5.9p1/monitor_wrap.c 2011-09-14 08:14:11.279520598 +0200 -@@ -707,10 +707,10 @@ mm_pty_allocate(int *ptyfd, int *ttyfd, - if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 || - (tmp2 = dup(pmonitor->m_recvfd)) == -1) { - error("%s: cannot allocate fds for pty", __func__); -- if (tmp1 > 0) -+ if (tmp1 >= 0) - close(tmp1); -- if (tmp2 > 0) -- close(tmp2); -+ /*DEAD CODE if (tmp2 >= 0) -+ close(tmp2);*/ - return 0; - } - close(tmp1); -diff -up openssh-5.9p1/openbsd-compat/bindresvport.c.coverity openssh-5.9p1/openbsd-compat/bindresvport.c ---- openssh-5.9p1/openbsd-compat/bindresvport.c.coverity 2010-12-03 00:50:26.000000000 +0100 -+++ openssh-5.9p1/openbsd-compat/bindresvport.c 2011-09-14 08:09:48.084459344 +0200 -@@ -58,7 +58,7 @@ bindresvport_sa(int sd, struct sockaddr - struct sockaddr_in6 *in6; - u_int16_t *portp; - u_int16_t port; -- socklen_t salen; -+ socklen_t salen = sizeof(struct sockaddr_storage); - int i; - - if (sa == NULL) { -diff -up openssh-5.9p1/packet.c.coverity openssh-5.9p1/packet.c ---- openssh-5.9p1/packet.c.coverity 2011-05-15 00:58:15.000000000 +0200 -+++ openssh-5.9p1/packet.c 2011-09-14 08:09:48.184587842 +0200 -@@ -1177,6 +1177,7 @@ packet_read_poll1(void) - case DEATTACK_DETECTED: - packet_disconnect("crc32 compensation attack: " - "network attack detected"); -+ break; - case DEATTACK_DOS_DETECTED: - packet_disconnect("deattack denial of " - "service detected"); -@@ -1684,7 +1685,7 @@ void - packet_write_wait(void) - { - fd_set *setp; -- int ret, ms_remain; -+ int ret, ms_remain = 0; - struct timeval start, timeout, *timeoutp = NULL; - - setp = (fd_set *)xcalloc(howmany(active_state->connection_out + 1, -diff -up openssh-5.9p1/progressmeter.c.coverity openssh-5.9p1/progressmeter.c ---- openssh-5.9p1/progressmeter.c.coverity 2006-08-05 04:39:40.000000000 +0200 -+++ openssh-5.9p1/progressmeter.c 2011-09-14 08:09:48.300586004 +0200 -@@ -65,7 +65,7 @@ static void update_progress_meter(int); - - static time_t start; /* start progress */ - static time_t last_update; /* last progress update */ --static char *file; /* name of the file being transferred */ -+static const char *file; /* name of the file being transferred */ - static off_t end_pos; /* ending position of transfer */ - static off_t cur_pos; /* transfer position as of last refresh */ - static volatile off_t *counter; /* progress counter */ -@@ -247,7 +247,7 @@ update_progress_meter(int ignore) - } - - void --start_progress_meter(char *f, off_t filesize, off_t *ctr) -+start_progress_meter(const char *f, off_t filesize, off_t *ctr) - { - start = last_update = time(NULL); - file = f; -diff -up openssh-5.9p1/progressmeter.h.coverity openssh-5.9p1/progressmeter.h ---- openssh-5.9p1/progressmeter.h.coverity 2006-03-26 05:30:02.000000000 +0200 -+++ openssh-5.9p1/progressmeter.h 2011-09-14 08:09:48.420645724 +0200 -@@ -23,5 +23,5 @@ - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - --void start_progress_meter(char *, off_t, off_t *); -+void start_progress_meter(const char *, off_t, off_t *); - void stop_progress_meter(void); -diff -up openssh-5.9p1/scp.c.coverity openssh-5.9p1/scp.c ---- openssh-5.9p1/scp.c.coverity 2011-01-06 12:41:21.000000000 +0100 -+++ openssh-5.9p1/scp.c 2011-09-14 08:09:48.531505457 +0200 -@@ -155,7 +155,7 @@ killchild(int signo) - { - if (do_cmd_pid > 1) { - kill(do_cmd_pid, signo ? signo : SIGTERM); -- waitpid(do_cmd_pid, NULL, 0); -+ (void) waitpid(do_cmd_pid, NULL, 0); - } - - if (signo) -diff -up openssh-5.9p1/servconf.c.coverity openssh-5.9p1/servconf.c ---- openssh-5.9p1/servconf.c.coverity 2011-06-23 00:30:03.000000000 +0200 -+++ openssh-5.9p1/servconf.c 2011-09-14 08:30:17.557468182 +0200 -@@ -609,7 +609,7 @@ match_cfg_line(char **condition, int lin - debug3("checking syntax for 'Match %s'", cp); - else - debug3("checking match for '%s' user %s host %s addr %s", cp, -- user ? user : "(null)", host ? host : "(null)", -+ user /* User is not NULL ? user : "(null)" */, host ? host : "(null)", - address ? address : "(null)"); - - while ((attrib = strdelim(&cp)) && *attrib != '\0') { -@@ -1171,7 +1171,7 @@ process_server_config_line(ServerOptions - fatal("%s line %d: Missing subsystem name.", - filename, linenum); - if (!*activep) { -- arg = strdelim(&cp); -+ /*arg =*/ (void) strdelim(&cp); - break; - } - for (i = 0; i < options->num_subsystems; i++) -@@ -1262,8 +1262,9 @@ process_server_config_line(ServerOptions - if (*activep && *charptr == NULL) { - *charptr = tilde_expand_filename(arg, getuid()); - /* increase optional counter */ -- if (intptr != NULL) -- *intptr = *intptr + 1; -+ /* DEAD CODE intptr is still NULL ;) -+ if (intptr != NULL) -+ *intptr = *intptr + 1; */ - } - break; - -diff -up openssh-5.9p1/serverloop.c.coverity openssh-5.9p1/serverloop.c ---- openssh-5.9p1/serverloop.c.coverity 2011-05-20 11:02:50.000000000 +0200 -+++ openssh-5.9p1/serverloop.c 2011-09-14 08:09:48.793586380 +0200 -@@ -147,13 +147,13 @@ notify_setup(void) - static void - notify_parent(void) - { -- if (notify_pipe[1] != -1) -+ if (notify_pipe[1] >= 0) - write(notify_pipe[1], "", 1); - } - static void - notify_prepare(fd_set *readset) - { -- if (notify_pipe[0] != -1) -+ if (notify_pipe[0] >= 0) - FD_SET(notify_pipe[0], readset); - } - static void -@@ -161,8 +161,8 @@ notify_done(fd_set *readset) - { - char c; - -- if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset)) -- while (read(notify_pipe[0], &c, 1) != -1) -+ if (notify_pipe[0] >= 0 && FD_ISSET(notify_pipe[0], readset)) -+ while (read(notify_pipe[0], &c, 1) >= 0) - debug2("notify_done: reading"); - } - -@@ -330,7 +330,7 @@ wait_until_can_do_something(fd_set **rea - * If we have buffered data, try to write some of that data - * to the program. - */ -- if (fdin != -1 && buffer_len(&stdin_buffer) > 0) -+ if (fdin >= 0 && buffer_len(&stdin_buffer) > 0) - FD_SET(fdin, *writesetp); - } - notify_prepare(*readsetp); -@@ -470,7 +470,7 @@ process_output(fd_set *writeset) - int len; - - /* Write buffered data to program stdin. */ -- if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) { -+ if (!compat20 && fdin >= 0 && FD_ISSET(fdin, writeset)) { - data = buffer_ptr(&stdin_buffer); - dlen = buffer_len(&stdin_buffer); - len = write(fdin, data, dlen); -@@ -583,7 +583,7 @@ server_loop(pid_t pid, int fdin_arg, int - set_nonblock(fdin); - set_nonblock(fdout); - /* we don't have stderr for interactive terminal sessions, see below */ -- if (fderr != -1) -+ if (fderr >= 0) - set_nonblock(fderr); - - if (!(datafellows & SSH_BUG_IGNOREMSG) && isatty(fdin)) -@@ -607,7 +607,7 @@ server_loop(pid_t pid, int fdin_arg, int - max_fd = MAX(connection_in, connection_out); - max_fd = MAX(max_fd, fdin); - max_fd = MAX(max_fd, fdout); -- if (fderr != -1) -+ if (fderr >= 0) - max_fd = MAX(max_fd, fderr); - #endif - -@@ -637,7 +637,7 @@ server_loop(pid_t pid, int fdin_arg, int - * If we have received eof, and there is no more pending - * input data, cause a real eof by closing fdin. - */ -- if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) { -+ if (stdin_eof && fdin >= 0 && buffer_len(&stdin_buffer) == 0) { - if (fdin != fdout) - close(fdin); - else -@@ -735,15 +735,15 @@ server_loop(pid_t pid, int fdin_arg, int - buffer_free(&stderr_buffer); - - /* Close the file descriptors. */ -- if (fdout != -1) -+ if (fdout >= 0) - close(fdout); - fdout = -1; - fdout_eof = 1; -- if (fderr != -1) -+ if (fderr >= 0) - close(fderr); - fderr = -1; - fderr_eof = 1; -- if (fdin != -1) -+ if (fdin >= 0) - close(fdin); - fdin = -1; - -@@ -937,7 +937,7 @@ server_input_window_size(int type, u_int - - debug("Window change received."); - packet_check_eom(); -- if (fdin != -1) -+ if (fdin >= 0) - pty_change_window_size(fdin, row, col, xpixel, ypixel); - } - -@@ -990,7 +990,7 @@ server_request_tun(void) - } - - tun = packet_get_int(); -- if (forced_tun_device != -1) { -+ if (forced_tun_device >= 0) { - if (tun != SSH_TUNID_ANY && forced_tun_device != tun) - goto done; - tun = forced_tun_device; -diff -up openssh-5.9p1/sftp-client.c.coverity openssh-5.9p1/sftp-client.c ---- openssh-5.9p1/sftp-client.c.coverity 2010-12-04 23:02:48.000000000 +0100 -+++ openssh-5.9p1/sftp-client.c 2011-09-14 08:09:48.910470343 +0200 -@@ -149,7 +149,7 @@ get_msg(struct sftp_conn *conn, Buffer * - } - - static void --send_string_request(struct sftp_conn *conn, u_int id, u_int code, char *s, -+send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s, - u_int len) - { - Buffer msg; -@@ -165,7 +165,7 @@ send_string_request(struct sftp_conn *co - - static void - send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, -- char *s, u_int len, Attrib *a) -+ const char *s, u_int len, Attrib *a) - { - Buffer msg; - -@@ -422,7 +422,7 @@ sftp_proto_version(struct sftp_conn *con - } - - int --do_close(struct sftp_conn *conn, char *handle, u_int handle_len) -+do_close(struct sftp_conn *conn, const char *handle, u_int handle_len) - { - u_int id, status; - Buffer msg; -@@ -447,7 +447,7 @@ do_close(struct sftp_conn *conn, char *h - - - static int --do_lsreaddir(struct sftp_conn *conn, char *path, int printflag, -+do_lsreaddir(struct sftp_conn *conn, const char *path, int printflag, - SFTP_DIRENT ***dir) - { - Buffer msg; -@@ -571,7 +571,7 @@ do_lsreaddir(struct sftp_conn *conn, cha - } - - int --do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir) -+do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir) - { - return(do_lsreaddir(conn, path, 0, dir)); - } -@@ -589,7 +589,7 @@ void free_sftp_dirents(SFTP_DIRENT **s) - } - - int --do_rm(struct sftp_conn *conn, char *path) -+do_rm(struct sftp_conn *conn, const char *path) - { - u_int status, id; - -@@ -604,7 +604,7 @@ do_rm(struct sftp_conn *conn, char *path - } - - int --do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int printflag) -+do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int printflag) - { - u_int status, id; - -@@ -620,7 +620,7 @@ do_mkdir(struct sftp_conn *conn, char *p - } - - int --do_rmdir(struct sftp_conn *conn, char *path) -+do_rmdir(struct sftp_conn *conn, const char *path) - { - u_int status, id; - -@@ -636,7 +636,7 @@ do_rmdir(struct sftp_conn *conn, char *p - } - - Attrib * --do_stat(struct sftp_conn *conn, char *path, int quiet) -+do_stat(struct sftp_conn *conn, const char *path, int quiet) - { - u_int id; - -@@ -650,7 +650,7 @@ do_stat(struct sftp_conn *conn, char *pa - } - - Attrib * --do_lstat(struct sftp_conn *conn, char *path, int quiet) -+do_lstat(struct sftp_conn *conn, const char *path, int quiet) - { - u_int id; - -@@ -684,7 +684,7 @@ do_fstat(struct sftp_conn *conn, char *h - #endif - - int --do_setstat(struct sftp_conn *conn, char *path, Attrib *a) -+do_setstat(struct sftp_conn *conn, const char *path, Attrib *a) - { - u_int status, id; - -@@ -701,7 +701,7 @@ do_setstat(struct sftp_conn *conn, char - } - - int --do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len, -+do_fsetstat(struct sftp_conn *conn, const char *handle, u_int handle_len, - Attrib *a) - { - u_int status, id; -@@ -718,12 +718,12 @@ do_fsetstat(struct sftp_conn *conn, char - } - - char * --do_realpath(struct sftp_conn *conn, char *path) -+do_realpath(struct sftp_conn *conn, const char *path) - { - Buffer msg; - u_int type, expected_id, count, id; - char *filename, *longname; -- Attrib *a; -+/*UNUSED Attrib *a; */ - - expected_id = id = conn->msg_id++; - send_string_request(conn, id, SSH2_FXP_REALPATH, path, -@@ -754,7 +754,7 @@ do_realpath(struct sftp_conn *conn, char - - filename = buffer_get_string(&msg, NULL); - longname = buffer_get_string(&msg, NULL); -- a = decode_attrib(&msg); -+ /*a =*/ (void) decode_attrib(&msg); - - debug3("SSH_FXP_REALPATH %s -> %s", path, filename); - -@@ -766,7 +766,7 @@ do_realpath(struct sftp_conn *conn, char - } - - int --do_rename(struct sftp_conn *conn, char *oldpath, char *newpath) -+do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath) - { - Buffer msg; - u_int status, id; -@@ -800,7 +800,7 @@ do_rename(struct sftp_conn *conn, char * - } - - int --do_hardlink(struct sftp_conn *conn, char *oldpath, char *newpath) -+do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) - { - Buffer msg; - u_int status, id; -@@ -833,7 +833,7 @@ do_hardlink(struct sftp_conn *conn, char - } - - int --do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath) -+do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) - { - Buffer msg; - u_int status, id; -@@ -984,7 +984,7 @@ send_read_request(struct sftp_conn *conn - } - - int --do_download(struct sftp_conn *conn, char *remote_path, char *local_path, -+do_download(struct sftp_conn *conn, const char *remote_path, const char *local_path, - Attrib *a, int pflag) - { - Attrib junk; -@@ -1223,7 +1223,7 @@ do_download(struct sftp_conn *conn, char - } - - static int --download_dir_internal(struct sftp_conn *conn, char *src, char *dst, -+download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, - Attrib *dirattrib, int pflag, int printflag, int depth) - { - int i, ret = 0; -@@ -1313,7 +1313,7 @@ download_dir_internal(struct sftp_conn * - } - - int --download_dir(struct sftp_conn *conn, char *src, char *dst, -+download_dir(struct sftp_conn *conn, const char *src, const char *dst, - Attrib *dirattrib, int pflag, int printflag) - { - char *src_canon; -@@ -1331,7 +1331,7 @@ download_dir(struct sftp_conn *conn, cha - } - - int --do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, -+do_upload(struct sftp_conn *conn, const char *local_path, const char *remote_path, - int pflag) - { - int local_fd; -@@ -1514,7 +1514,7 @@ do_upload(struct sftp_conn *conn, char * - } - - static int --upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, -+upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, - int pflag, int printflag, int depth) - { - int ret = 0, status; -@@ -1605,7 +1605,7 @@ upload_dir_internal(struct sftp_conn *co - } - - int --upload_dir(struct sftp_conn *conn, char *src, char *dst, int printflag, -+upload_dir(struct sftp_conn *conn, const char *src, const char *dst, int printflag, - int pflag) - { - char *dst_canon; -@@ -1622,7 +1622,7 @@ upload_dir(struct sftp_conn *conn, char - } - - char * --path_append(char *p1, char *p2) -+path_append(const char *p1, const char *p2) - { - char *ret; - size_t len = strlen(p1) + strlen(p2) + 2; -diff -up openssh-5.9p1/sftp-client.h.coverity openssh-5.9p1/sftp-client.h ---- openssh-5.9p1/sftp-client.h.coverity 2010-12-04 23:02:48.000000000 +0100 -+++ openssh-5.9p1/sftp-client.h 2011-09-14 08:09:49.021583940 +0200 -@@ -56,49 +56,49 @@ struct sftp_conn *do_init(int, int, u_in - u_int sftp_proto_version(struct sftp_conn *); - - /* Close file referred to by 'handle' */ --int do_close(struct sftp_conn *, char *, u_int); -+int do_close(struct sftp_conn *, const char *, u_int); - - /* Read contents of 'path' to NULL-terminated array 'dir' */ --int do_readdir(struct sftp_conn *, char *, SFTP_DIRENT ***); -+int do_readdir(struct sftp_conn *, const char *, SFTP_DIRENT ***); - - /* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from do_readdir) */ - void free_sftp_dirents(SFTP_DIRENT **); - - /* Delete file 'path' */ --int do_rm(struct sftp_conn *, char *); -+int do_rm(struct sftp_conn *, const char *); - - /* Create directory 'path' */ --int do_mkdir(struct sftp_conn *, char *, Attrib *, int); -+int do_mkdir(struct sftp_conn *, const char *, Attrib *, int); - - /* Remove directory 'path' */ --int do_rmdir(struct sftp_conn *, char *); -+int do_rmdir(struct sftp_conn *, const char *); - - /* Get file attributes of 'path' (follows symlinks) */ --Attrib *do_stat(struct sftp_conn *, char *, int); -+Attrib *do_stat(struct sftp_conn *, const char *, int); - - /* Get file attributes of 'path' (does not follow symlinks) */ --Attrib *do_lstat(struct sftp_conn *, char *, int); -+Attrib *do_lstat(struct sftp_conn *, const char *, int); - - /* Set file attributes of 'path' */ --int do_setstat(struct sftp_conn *, char *, Attrib *); -+int do_setstat(struct sftp_conn *, const char *, Attrib *); - - /* Set file attributes of open file 'handle' */ --int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *); -+int do_fsetstat(struct sftp_conn *, const char *, u_int, Attrib *); - - /* Canonicalise 'path' - caller must free result */ --char *do_realpath(struct sftp_conn *, char *); -+char *do_realpath(struct sftp_conn *, const char *); - - /* Get statistics for filesystem hosting file at "path" */ - int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int); - - /* Rename 'oldpath' to 'newpath' */ --int do_rename(struct sftp_conn *, char *, char *); -+int do_rename(struct sftp_conn *, const char *, const char *); - - /* Link 'oldpath' to 'newpath' */ --int do_hardlink(struct sftp_conn *, char *, char *); -+int do_hardlink(struct sftp_conn *, const char *, const char *); - --/* Rename 'oldpath' to 'newpath' */ --int do_symlink(struct sftp_conn *, char *, char *); -+/* Symlink 'oldpath' to 'newpath' */ -+int do_symlink(struct sftp_conn *, const char *, const char *); - - /* XXX: add callbacks to do_download/do_upload so we can do progress meter */ - -@@ -106,27 +106,27 @@ int do_symlink(struct sftp_conn *, char - * Download 'remote_path' to 'local_path'. Preserve permissions and times - * if 'pflag' is set - */ --int do_download(struct sftp_conn *, char *, char *, Attrib *, int); -+int do_download(struct sftp_conn *, const char *, const char *, Attrib *, int); - - /* - * Recursively download 'remote_directory' to 'local_directory'. Preserve - * times if 'pflag' is set - */ --int download_dir(struct sftp_conn *, char *, char *, Attrib *, int, int); -+int download_dir(struct sftp_conn *, const char *, const char *, Attrib *, int, int); - - /* - * Upload 'local_path' to 'remote_path'. Preserve permissions and times - * if 'pflag' is set - */ --int do_upload(struct sftp_conn *, char *, char *, int); -+int do_upload(struct sftp_conn *, const char *, const char *, int); - - /* - * Recursively upload 'local_directory' to 'remote_directory'. Preserve - * times if 'pflag' is set - */ --int upload_dir(struct sftp_conn *, char *, char *, int, int); -+int upload_dir(struct sftp_conn *, const char *, const char *, int, int); - - /* Concatenate paths, taking care of slashes. Caller must free result. */ --char *path_append(char *, char *); -+char *path_append(const char *, const char *); - - #endif -diff -up openssh-5.9p1/sftp.c.coverity openssh-5.9p1/sftp.c ---- openssh-5.9p1/sftp.c.coverity 2010-12-04 23:02:48.000000000 +0100 -+++ openssh-5.9p1/sftp.c 2011-09-14 08:09:49.468493585 +0200 -@@ -206,7 +206,7 @@ killchild(int signo) - { - if (sshpid > 1) { - kill(sshpid, SIGTERM); -- waitpid(sshpid, NULL, 0); -+ (void) waitpid(sshpid, NULL, 0); - } - - _exit(1); -@@ -316,7 +316,7 @@ local_do_ls(const char *args) - - /* Strip one path (usually the pwd) from the start of another */ - static char * --path_strip(char *path, char *strip) -+path_strip(const char *path, const char *strip) - { - size_t len; - -@@ -334,7 +334,7 @@ path_strip(char *path, char *strip) - } - - static char * --make_absolute(char *p, char *pwd) -+make_absolute(char *p, const char *pwd) - { - char *abs_str; - -@@ -482,7 +482,7 @@ parse_df_flags(const char *cmd, char **a - } - - static int --is_dir(char *path) -+is_dir(const char *path) - { - struct stat sb; - -@@ -494,7 +494,7 @@ is_dir(char *path) - } - - static int --remote_is_dir(struct sftp_conn *conn, char *path) -+remote_is_dir(struct sftp_conn *conn, const char *path) - { - Attrib *a; - -@@ -508,7 +508,7 @@ remote_is_dir(struct sftp_conn *conn, ch - - /* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */ - static int --pathname_is_dir(char *pathname) -+pathname_is_dir(const char *pathname) - { - size_t l = strlen(pathname); - -@@ -516,7 +516,7 @@ pathname_is_dir(char *pathname) - } - - static int --process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, -+process_get(struct sftp_conn *conn, const char *src, const char *dst, const char *pwd, - int pflag, int rflag) - { - char *abs_src = NULL; -@@ -590,7 +590,7 @@ out: - } - - static int --process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, -+process_put(struct sftp_conn *conn, const char *src, const char *dst, const char *pwd, - int pflag, int rflag) - { - char *tmp_dst = NULL; -@@ -695,7 +695,7 @@ sdirent_comp(const void *aa, const void - - /* sftp ls.1 replacement for directories */ - static int --do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag) -+do_ls_dir(struct sftp_conn *conn, const char *path, const char *strip_path, int lflag) - { - int n; - u_int c = 1, colspace = 0, columns = 1; -@@ -780,10 +780,10 @@ do_ls_dir(struct sftp_conn *conn, char * - - /* sftp ls.1 replacement which handles path globs */ - static int --do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path, -+do_globbed_ls(struct sftp_conn *conn, const char *path, const char *strip_path, - int lflag) - { -- Attrib *a = NULL; -+/*UNUSED Attrib *a = NULL;*/ - char *fname, *lname; - glob_t g; - int err; -@@ -828,7 +828,7 @@ do_globbed_ls(struct sftp_conn *conn, ch - colspace = width / columns; - } - -- for (i = 0; g.gl_pathv[i] && !interrupted; i++, a = NULL) { -+ for (i = 0; g.gl_pathv[i] && !interrupted; i++/*, a = NULL*/) { - fname = path_strip(g.gl_pathv[i], strip_path); - if (lflag & LS_LONG_VIEW) { - if (g.gl_statv[i] == NULL) { -@@ -861,7 +861,7 @@ do_globbed_ls(struct sftp_conn *conn, ch - } - - static int --do_df(struct sftp_conn *conn, char *path, int hflag, int iflag) -+do_df(struct sftp_conn *conn, const char *path, int hflag, int iflag) - { - struct sftp_statvfs st; - char s_used[FMT_SCALED_STRSIZE]; -diff -up openssh-5.9p1/ssh-agent.c.coverity openssh-5.9p1/ssh-agent.c ---- openssh-5.9p1/ssh-agent.c.coverity 2011-06-03 06:14:16.000000000 +0200 -+++ openssh-5.9p1/ssh-agent.c 2011-09-14 08:09:49.572460295 +0200 -@@ -1147,8 +1147,8 @@ main(int ac, char **av) - sanitise_stdfd(); - - /* drop */ -- setegid(getgid()); -- setgid(getgid()); -+ (void) setegid(getgid()); -+ (void) setgid(getgid()); - - #if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) - /* Disable ptrace on Linux without sgid bit */ -diff -up openssh-5.9p1/sshd.c.coverity openssh-5.9p1/sshd.c ---- openssh-5.9p1/sshd.c.coverity 2011-06-23 11:45:51.000000000 +0200 -+++ openssh-5.9p1/sshd.c 2011-09-14 08:09:49.687509968 +0200 -@@ -676,8 +676,10 @@ privsep_preauth(Authctxt *authctxt) - if (getuid() == 0 || geteuid() == 0) - privsep_preauth_child(); - setproctitle("%s", "[net]"); -- if (box != NULL) -+ if (box != NULL) { - ssh_sandbox_child(box); -+ xfree(box); -+ } - - return 0; - } -@@ -1302,6 +1304,9 @@ server_accept_loop(int *sock_in, int *so - if (num_listen_socks < 0) - break; - } -+ -+ if (fdset != NULL) -+ xfree(fdset); - } - - -@@ -1774,7 +1779,7 @@ main(int ac, char **av) - - /* Chdir to the root directory so that the current disk can be - unmounted if desired. */ -- chdir("/"); -+ (void) chdir("/"); - - /* ignore SIGPIPE */ - signal(SIGPIPE, SIG_IGN); diff --git a/openssh-5.9p1-kuserok.patch b/openssh-5.9p1-kuserok.patch deleted file mode 100644 index 11f38a5..0000000 --- a/openssh-5.9p1-kuserok.patch +++ /dev/null @@ -1,167 +0,0 @@ -diff -up openssh-5.9p0/auth-krb5.c.kuserok openssh-5.9p0/auth-krb5.c ---- openssh-5.9p0/auth-krb5.c.kuserok 2011-08-30 16:37:32.651150128 +0200 -+++ openssh-5.9p0/auth-krb5.c 2011-08-30 16:37:37.549087368 +0200 -@@ -54,6 +54,20 @@ - - extern ServerOptions options; - -+int -+ssh_krb5_kuserok(krb5_context krb5_ctx, krb5_principal krb5_user, const char *client) -+{ -+ if (options.use_kuserok) -+ return krb5_kuserok(krb5_ctx, krb5_user, client); -+ else { -+ char kuser[65]; -+ -+ if (krb5_aname_to_localname(krb5_ctx, krb5_user, sizeof(kuser), kuser)) -+ return 0; -+ return strcmp(kuser, client) == 0; -+ } -+} -+ - static int - krb5_init(void *context) - { -@@ -146,7 +160,7 @@ auth_krb5_password(Authctxt *authctxt, c - if (problem) - goto out; - -- if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) { -+ if (!ssh_krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) { - problem = -1; - goto out; - } -diff -up openssh-5.9p0/gss-serv-krb5.c.kuserok openssh-5.9p0/gss-serv-krb5.c ---- openssh-5.9p0/gss-serv-krb5.c.kuserok 2011-08-30 16:37:36.988024804 +0200 -+++ openssh-5.9p0/gss-serv-krb5.c 2011-08-30 16:37:37.659088030 +0200 -@@ -68,6 +68,7 @@ static int ssh_gssapi_krb5_cmdok(krb5_pr - int); - - static krb5_context krb_context = NULL; -+extern int ssh_krb5_kuserok(krb5_context, krb5_principal, const char *); - - /* Initialise the krb5 library, for the stuff that GSSAPI won't do */ - -@@ -115,7 +116,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client - /* NOTE: .k5login and .k5users must opened as root, not the user, - * because if they are on a krb5-protected filesystem, user credentials - * to access these files aren't available yet. */ -- if (krb5_kuserok(krb_context, princ, luser) && k5login_exists) { -+ if (ssh_krb5_kuserok(krb_context, princ, luser) && k5login_exists) { - retval = 1; - logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", - luser, (char *)client->displayname.value); -diff -up openssh-5.9p0/servconf.c.kuserok openssh-5.9p0/servconf.c ---- openssh-5.9p0/servconf.c.kuserok 2011-08-30 16:37:35.093073603 +0200 -+++ openssh-5.9p0/servconf.c 2011-08-30 16:41:13.568087145 +0200 -@@ -144,6 +144,7 @@ initialize_server_options(ServerOptions - options->authorized_principals_file = NULL; - options->ip_qos_interactive = -1; - options->ip_qos_bulk = -1; -+ options->use_kuserok = -1; - } - - void -@@ -291,6 +292,8 @@ fill_default_server_options(ServerOption - options->ip_qos_bulk = IPTOS_THROUGHPUT; - if (options->show_patchlevel == -1) - options->show_patchlevel = 0; -+ if (options->use_kuserok == -1) -+ options->use_kuserok = 1; - - /* Turn privilege separation on by default */ - if (use_privsep == -1) -@@ -317,7 +320,7 @@ typedef enum { - sPermitRootLogin, sLogFacility, sLogLevel, - sRhostsRSAAuthentication, sRSAAuthentication, - sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, -- sKerberosGetAFSToken, -+ sKerberosGetAFSToken, sKerberosUseKuserok, - sKerberosTgtPassing, sChallengeResponseAuthentication, - sPasswordAuthentication, sKbdInteractiveAuthentication, - sListenAddress, sAddressFamily, -@@ -388,11 +391,13 @@ static struct { - #else - { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, - #endif -+ { "kerberosusekuserok", sKerberosUseKuserok, SSHCFG_ALL }, - #else - { "kerberosauthentication", sUnsupported, SSHCFG_ALL }, - { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL }, - { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL }, - { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, -+ { "kerberosusekuserok", sUnsupported, SSHCFG_ALL }, - #endif - { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, - { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, -@@ -1371,6 +1376,10 @@ process_server_config_line(ServerOptions - *activep = value; - break; - -+ case sKerberosUseKuserok: -+ intptr = &options->use_kuserok; -+ goto parse_flag; -+ - case sPermitOpen: - arg = strdelim(&cp); - if (!arg || *arg == '\0') -@@ -1580,6 +1589,7 @@ copy_set_server_options(ServerOptions *d - M_CP_INTOPT(max_authtries); - M_CP_INTOPT(ip_qos_interactive); - M_CP_INTOPT(ip_qos_bulk); -+ M_CP_INTOPT(use_kuserok); - - /* See comment in servconf.h */ - COPY_MATCH_STRING_OPTS(); -@@ -1816,6 +1826,7 @@ dump_config(ServerOptions *o) - dump_cfg_fmtint(sUseDNS, o->use_dns); - dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); - dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); -+ dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok); - - /* string arguments */ - dump_cfg_string(sPidFile, o->pid_file); -diff -up openssh-5.9p0/servconf.h.kuserok openssh-5.9p0/servconf.h ---- openssh-5.9p0/servconf.h.kuserok 2011-08-30 16:37:35.201051957 +0200 -+++ openssh-5.9p0/servconf.h 2011-08-30 16:37:37.926087431 +0200 -@@ -166,6 +166,7 @@ typedef struct { - - int num_permitted_opens; - -+ int use_kuserok; - char *chroot_directory; - char *revoked_keys_file; - char *trusted_user_ca_keys; -diff -up openssh-5.9p0/sshd_config.5.kuserok openssh-5.9p0/sshd_config.5 ---- openssh-5.9p0/sshd_config.5.kuserok 2011-08-30 16:37:35.979024607 +0200 -+++ openssh-5.9p0/sshd_config.5 2011-08-30 16:37:38.040087843 +0200 -@@ -603,6 +603,10 @@ Specifies whether to automatically destr - file on logout. - The default is - .Dq yes . -+.It Cm KerberosUseKuserok -+Specifies whether to look at .k5login file for user's aliases. -+The default is -+.Dq yes . - .It Cm KexAlgorithms - Specifies the available KEX (Key Exchange) algorithms. - Multiple algorithms must be comma-separated. -@@ -746,6 +750,7 @@ Available keywords are - .Cm HostbasedUsesNameFromPacketOnly , - .Cm KbdInteractiveAuthentication , - .Cm KerberosAuthentication , -+.Cm KerberosUseKuserok , - .Cm MaxAuthTries , - .Cm MaxSessions , - .Cm PubkeyAuthentication , -diff -up openssh-5.9p0/sshd_config.kuserok openssh-5.9p0/sshd_config ---- openssh-5.9p0/sshd_config.kuserok 2011-08-30 16:37:36.808026328 +0200 -+++ openssh-5.9p0/sshd_config 2011-08-30 16:37:38.148071520 +0200 -@@ -77,6 +77,7 @@ ChallengeResponseAuthentication no - #KerberosOrLocalPasswd yes - #KerberosTicketCleanup yes - #KerberosGetAFSToken no -+#KerberosUseKuserok yes - - # GSSAPI options - #GSSAPIAuthentication no diff --git a/openssh-5.9p1-log-usepam-no.patch b/openssh-5.9p1-log-usepam-no.patch deleted file mode 100644 index 614d2cd..0000000 --- a/openssh-5.9p1-log-usepam-no.patch +++ /dev/null @@ -1,28 +0,0 @@ -diff --git a/sshd.c b/sshd.c -index 8dcfdf2..95b63ad 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -1592,6 +1592,10 @@ main(int ac, char **av) - parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, - &cfg, NULL, NULL, NULL); - -+ /* 'UsePAM no' is not supported in Fedora */ -+ if (! options.use_pam) -+ logit("WARNING: 'UsePAM no' is not supported in Fedora and may cause several problems."); -+ - seed_rng(); - - /* Fill in default values for those options not explicitly set. */ -diff --git a/sshd_config b/sshd_config -index 8c16754..9f28b04 100644 ---- a/sshd_config -+++ b/sshd_config -@@ -92,6 +92,8 @@ GSSAPICleanupCredentials yes - # If you just want the PAM account and session checks to run without - # PAM authentication, then enable this but set PasswordAuthentication - # and ChallengeResponseAuthentication to 'no'. -+# WARNING: 'UsePAM no' is not supported in Fedora and may cause several -+# problems. - #UsePAM no - UsePAM yes - diff --git a/openssh-5.9p1-null-xcrypt.patch b/openssh-5.9p1-null-xcrypt.patch deleted file mode 100644 index 50f32ff..0000000 --- a/openssh-5.9p1-null-xcrypt.patch +++ /dev/null @@ -1,17 +0,0 @@ -Index: auth-passwd.c -=================================================================== -RCS file: /cvs/openssh/auth-passwd.c,v -retrieving revision 1.90 -retrieving revision 1.91 -diff -u -r1.90 -r1.91 ---- auth-passwd.c 8 Mar 2009 00:40:28 -0000 1.90 -+++ auth-passwd.c 25 Apr 2012 23:51:28 -0000 1.91 -@@ -209,6 +209,7 @@ - * Authentication is accepted if the encrypted passwords - * are identical. - */ -- return (strcmp(encrypted_password, pw_password) == 0); -+ return encrypted_password != NULL && -+ strcmp(encrypted_password, pw_password) == 0; - } - #endif diff --git a/openssh-5.9p1-required-authentications.patch b/openssh-5.9p1-required-authentications.patch deleted file mode 100644 index cecbffc..0000000 --- a/openssh-5.9p1-required-authentications.patch +++ /dev/null @@ -1,828 +0,0 @@ -diff -up openssh-5.9p1/auth.c.required-authentication openssh-5.9p1/auth.c ---- openssh-5.9p1/auth.c.required-authentication 2012-07-27 12:21:41.181601972 +0200 -+++ openssh-5.9p1/auth.c 2012-07-27 12:21:41.203602020 +0200 -@@ -251,7 +251,8 @@ allowed_user(struct passwd * pw) - } - - void --auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) -+auth_log(Authctxt *authctxt, int authenticated, const char *method, -+ const char *submethod, const char *info) - { - void (*authlog) (const char *fmt,...) = verbose; - char *authmsg; -@@ -271,9 +272,10 @@ auth_log(Authctxt *authctxt, int authent - else - authmsg = authenticated ? "Accepted" : "Failed"; - -- authlog("%s %s for %s%.100s from %.200s port %d%s", -+ authlog("%s %s%s%s for %s%.100s from %.200s port %d%s", - authmsg, - method, -+ submethod == NULL ? "" : "/", submethod == NULL ? "" : submethod, - authctxt->valid ? "" : "invalid user ", - authctxt->user, - get_remote_ipaddr(), -@@ -303,7 +305,7 @@ auth_log(Authctxt *authctxt, int authent - * Check whether root logins are disallowed. - */ - int --auth_root_allowed(char *method) -+auth_root_allowed(const char *method) - { - switch (options.permit_root_login) { - case PERMIT_YES: -@@ -694,3 +696,57 @@ fakepw(void) - - return (&fake); - } -+ -+int -+auth_method_in_list(const char *list, const char *method) -+{ -+ char *cp; -+ -+ cp = match_list(method, list, NULL); -+ if (cp != NULL) { -+ xfree(cp); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+#define DELIM "," -+int -+auth_remove_from_list(char **list, const char *method) -+{ -+ char *oldlist, *cp, *newlist = NULL; -+ u_int len = 0, ret = 0; -+ -+ if (list == NULL || *list == NULL) -+ return (0); -+ -+ oldlist = *list; -+ len = strlen(oldlist) + 1; -+ newlist = xmalloc(len); -+ memset(newlist, '\0', len); -+ -+ /* Remove method from list, if present */ -+ for (;;) { -+ if ((cp = strsep(&oldlist, DELIM)) == NULL) -+ break; -+ if (*cp == '\0') -+ continue; -+ if (strcmp(cp, method) != 0) { -+ if (*newlist != '\0') -+ strlcat(newlist, DELIM, len); -+ strlcat(newlist, cp, len); -+ } else -+ ret++; -+ } -+ -+ /* Return NULL instead of empty list */ -+ if (*newlist == '\0') { -+ xfree(newlist); -+ newlist = NULL; -+ } -+ xfree(*list); -+ *list = newlist; -+ -+ return (ret); -+} -diff -up openssh-5.9p1/auth.h.required-authentication openssh-5.9p1/auth.h ---- openssh-5.9p1/auth.h.required-authentication 2011-05-29 13:39:38.000000000 +0200 -+++ openssh-5.9p1/auth.h 2012-07-27 12:21:41.204602022 +0200 -@@ -142,10 +142,11 @@ void disable_forwarding(void); - void do_authentication(Authctxt *); - void do_authentication2(Authctxt *); - --void auth_log(Authctxt *, int, char *, char *); --void userauth_finish(Authctxt *, int, char *); -+void auth_log(Authctxt *, int, const char *, const char *, const char *); -+void userauth_finish(Authctxt *, int, const char *, const char *); -+int auth_root_allowed(const char *); -+ - void userauth_send_banner(const char *); --int auth_root_allowed(char *); - - char *auth2_read_banner(void); - -@@ -192,6 +193,11 @@ void auth_debug_send(void); - void auth_debug_reset(void); - - struct passwd *fakepw(void); -+int auth_method_in_list(const char *, const char *); -+int auth_remove_from_list(char **, const char *); -+ -+int auth1_check_required(const char *); -+int auth2_check_required(const char *); - - int sys_auth_passwd(Authctxt *, const char *); - -diff -up openssh-5.9p1/auth1.c.required-authentication openssh-5.9p1/auth1.c ---- openssh-5.9p1/auth1.c.required-authentication 2010-08-31 14:36:39.000000000 +0200 -+++ openssh-5.9p1/auth1.c 2012-07-27 12:50:50.708706675 +0200 -@@ -98,6 +98,55 @@ static const struct AuthMethod1 - return (NULL); - } - -+static const struct AuthMethod1 * -+lookup_authmethod1_by_name(const char *name) -+{ -+ int i; -+ -+ for (i = 0; auth1_methods[i].name != NULL; i++) -+ if (strcmp(auth1_methods[i].name, name) == 0) -+ return (&(auth1_methods[i])); -+ -+ return NULL; -+} -+ -+#define DELIM "," -+int -+auth1_check_required(const char *list) -+{ -+ char *orig_methods, *methods, *cp; -+ static const struct AuthMethod1 *m; -+ int ret = 0; -+ -+ orig_methods = methods = xstrdup(list); -+ for(;;) { /* XXX maybe: while ((cp = ...) != NULL) ? */ -+ if ((cp = strsep(&methods, DELIM)) == NULL) -+ break; -+ debug2("auth1_check_required: method \"%s\"", cp); -+ if (*cp == '\0') { -+ debug("auth1_check_required: empty method"); -+ ret = -1; -+ } -+ if ((m = lookup_authmethod1_by_name(cp)) == NULL) { -+ debug("auth1_check_required: unknown method " -+ "\"%s\"", cp); -+ ret = -1; -+ break; -+ } -+ if (*(m->enabled) == 0) { -+ debug("auth1_check_required: method %s explicitly " -+ "disabled", cp); -+ ret = -1; -+ } -+ /* Activate method if it isn't already */ -+ if (*(m->enabled) == -1) -+ *(m->enabled) = 1; -+ } -+ xfree(orig_methods); -+ return (ret); -+} -+ -+ - static char * - get_authname(int type) - { -@@ -237,6 +286,7 @@ do_authloop(Authctxt *authctxt) - { - int authenticated = 0; - char info[1024]; -+ const char *meth_name; - int prev = 0, type = 0; - const struct AuthMethod1 *meth; - -@@ -244,7 +294,7 @@ do_authloop(Authctxt *authctxt) - authctxt->valid ? "" : "invalid user ", authctxt->user); - - /* If the user has no password, accept authentication immediately. */ -- if (options.permit_empty_passwd && options.password_authentication && -+ if (options.permit_empty_passwd && options.password_authentication && options.password_authentication && - #ifdef KRB5 - (!options.kerberos_authentication || options.kerberos_or_local_passwd) && - #endif -@@ -253,7 +303,7 @@ do_authloop(Authctxt *authctxt) - if (options.use_pam && (PRIVSEP(do_pam_account()))) - #endif - { -- auth_log(authctxt, 1, "without authentication", ""); -+ auth_log(authctxt, 1, "without authentication", NULL, ""); - return; - } - } -@@ -272,6 +322,7 @@ do_authloop(Authctxt *authctxt) - /* Get a packet from the client. */ - prev = type; - type = packet_read(); -+ meth_name = get_authname(type); - - /* - * If we started challenge-response authentication but the -@@ -287,8 +338,8 @@ do_authloop(Authctxt *authctxt) - if (authctxt->failures >= options.max_authtries) - goto skip; - if ((meth = lookup_authmethod1(type)) == NULL) { -- logit("Unknown message during authentication: " -- "type %d", type); -+ logit("Unknown message during authentication: type %d", -+ type); - goto skip; - } - -@@ -297,6 +348,17 @@ do_authloop(Authctxt *authctxt) - goto skip; - } - -+ /* -+ * Skip methods not in required list, until all the required -+ * ones are done -+ */ -+ if (options.required_auth1 != NULL && -+ !auth_method_in_list(options.required_auth1, meth_name)) { -+ debug("Skipping method \"%s\" until required " -+ "authentication completed", meth_name); -+ goto skip; -+ } -+ - authenticated = meth->method(authctxt, info, sizeof(info)); - if (authenticated == -1) - continue; /* "postponed" */ -@@ -352,7 +414,29 @@ do_authloop(Authctxt *authctxt) - - skip: - /* Log before sending the reply */ -- auth_log(authctxt, authenticated, get_authname(type), info); -+ auth_log(authctxt, authenticated, meth_name, NULL, info); -+ -+ /* Loop until the required authmethods are done */ -+ if (authenticated && options.required_auth1 != NULL) { -+ if (auth_remove_from_list(&options.required_auth1, -+ meth_name) == 0) -+ fatal("INTERNAL ERROR: authenticated method " -+ "\"%s\" not in required list \"%s\"", -+ meth_name, options.required_auth1); -+ debug2("do_authloop: required list now: %s", -+ options.required_auth1 == NULL ? -+ "DONE" : options.required_auth1); -+ if (options.required_auth1 == NULL) -+ return; -+ authenticated = 0; -+ /* -+ * Disable method so client can't authenticate with it -+ * after the required authentications are complete. -+ */ -+ *(meth->enabled) = 0; -+ packet_send_debug("Further authentication required"); -+ goto send_fail; -+ } - - if (client_user != NULL) { - xfree(client_user); -@@ -368,6 +452,7 @@ do_authloop(Authctxt *authctxt) - #endif - packet_disconnect(AUTH_FAIL_MSG, authctxt->user); - } -+ send_fail: - - packet_start(SSH_SMSG_FAILURE); - packet_send(); -diff -up openssh-5.9p1/auth2.c.required-authentication openssh-5.9p1/auth2.c ---- openssh-5.9p1/auth2.c.required-authentication 2011-05-05 06:04:11.000000000 +0200 -+++ openssh-5.9p1/auth2.c 2012-07-27 12:51:59.048241612 +0200 -@@ -215,7 +215,7 @@ input_userauth_request(int type, u_int32 - { - Authctxt *authctxt = ctxt; - Authmethod *m = NULL; -- char *user, *service, *method, *style = NULL; -+ char *user, *service, *method, *active_methods, *style = NULL; - int authenticated = 0; - - if (authctxt == NULL) -@@ -277,22 +277,31 @@ input_userauth_request(int type, u_int32 - authctxt->server_caused_failure = 0; - - /* try to authenticate user */ -- m = authmethod_lookup(method); -- if (m != NULL && authctxt->failures < options.max_authtries) { -- debug2("input_userauth_request: try method %s", method); -- authenticated = m->userauth(authctxt); -- } -- userauth_finish(authctxt, authenticated, method); -+ active_methods = authmethods_get(); -+ if (strcmp(method, "none") == 0 || -+ auth_method_in_list(active_methods, method)) { -+ m = authmethod_lookup(method); -+ if (m != NULL) { -+ debug2("input_userauth_request: try method %s", method); -+ authenticated = m->userauth(authctxt); -+ } - -+ } -+ xfree(active_methods); -+ userauth_finish(authctxt, authenticated, method, NULL); -+ - xfree(service); - xfree(user); - xfree(method); - } - - void --userauth_finish(Authctxt *authctxt, int authenticated, char *method) -+userauth_finish(Authctxt *authctxt, int authenticated, const char *method, -+ const char *submethod) - { - char *methods; -+ Authmethod *m = NULL; -+ u_int partial = 0; - - if (!authctxt->valid && authenticated) - fatal("INTERNAL ERROR: authenticated invalid user %s", -@@ -330,12 +339,42 @@ userauth_finish(Authctxt *authctxt, int - #endif /* _UNICOS */ - - /* Log before sending the reply */ -- auth_log(authctxt, authenticated, method, " ssh2"); -+ auth_log(authctxt, authenticated, method, submethod, " ssh2"); - - if (authctxt->postponed) - return; - -- /* XXX todo: check if multiple auth methods are needed */ -+ /* Handle RequiredAuthentications2: loop until required methods done */ -+ if (authenticated && options.required_auth2 != NULL) { -+ if ((m = authmethod_lookup(method)) == NULL) -+ fatal("INTERNAL ERROR: authenticated method " -+ "\"%s\" unknown", method); -+ if (auth_remove_from_list(&options.required_auth2, method) == 0) -+ fatal("INTERNAL ERROR: authenticated method " -+ "\"%s\" not in required list \"%s\"", -+ method, options.required_auth2); -+ debug2("userauth_finish: required list now: %s", -+ options.required_auth2 == NULL ? -+ "DONE" : options.required_auth2); -+ /* -+ * if authenticated and no more required methods -+ * then declare success -+ */ -+ if ( authenticated && options.required_auth2 == NULL ) { -+ debug2("userauth_finish: authenticated and no more required methods"); -+ } else { -+ /* -+ * Disable method so client can't authenticate with it after -+ * the required authentications are complete. -+ */ -+ if (m->enabled != NULL) -+ *(m->enabled) = 0; -+ authenticated = 0; -+ partial = 1; -+ goto send_fail; -+ } -+ } -+ - if (authenticated == 1) { - /* turn off userauth */ - dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); -@@ -345,7 +384,6 @@ userauth_finish(Authctxt *authctxt, int - /* now we can break out */ - authctxt->success = 1; - } else { -- - /* Allow initial try of "none" auth without failure penalty */ - if (!authctxt->server_caused_failure && - (authctxt->attempt > 1 || strcmp(method, "none") != 0)) -@@ -356,10 +394,11 @@ userauth_finish(Authctxt *authctxt, int - #endif - packet_disconnect(AUTH_FAIL_MSG, authctxt->user); - } -+ send_fail: - methods = authmethods_get(); - packet_start(SSH2_MSG_USERAUTH_FAILURE); - packet_put_cstring(methods); -- packet_put_char(0); /* XXX partial success, unused */ -+ packet_put_char(partial); - packet_send(); - packet_write_wait(); - xfree(methods); -@@ -373,6 +412,9 @@ authmethods_get(void) - char *list; - int i; - -+ if (options.required_auth2 != NULL) -+ return xstrdup(options.required_auth2); -+ - buffer_init(&b); - for (i = 0; authmethods[i] != NULL; i++) { - if (strcmp(authmethods[i]->name, "none") == 0) -@@ -407,3 +449,43 @@ authmethod_lookup(const char *name) - return NULL; - } - -+#define DELIM "," -+ -+int -+auth2_check_required(const char *list) -+{ -+ char *orig_methods, *methods, *cp; -+ struct Authmethod *m; -+ int i, ret = 0; -+ -+ orig_methods = methods = xstrdup(list); -+ for(;;) { -+ if ((cp = strsep(&methods, DELIM)) == NULL) -+ break; -+ debug2("auth2_check_required: method \"%s\"", cp); -+ if (*cp == '\0') { -+ debug("auth2_check_required: empty method"); -+ ret = -1; -+ } -+ for (i = 0; authmethods[i] != NULL; i++) -+ if (strcmp(cp, authmethods[i]->name) == 0) -+ break; -+ if ((m = authmethods[i]) == NULL) { -+ debug("auth2_check_required: unknown method " -+ "\"%s\"", cp); -+ ret = -1; -+ break; -+ } -+ if (m->enabled == NULL || *(m->enabled) == 0) { -+ debug("auth2_check_required: method %s explicitly " -+ "disabled", cp); -+ ret = -1; -+ } -+ /* Activate method if it isn't already */ -+ if (m->enabled != NULL && *(m->enabled) == -1) -+ *(m->enabled) = 1; -+ } -+ xfree(orig_methods); -+ return (ret); -+} -+ -diff -up openssh-5.9p1/auth2-gss.c.required-authentication openssh-5.9p1/auth2-gss.c ---- openssh-5.9p1/auth2-gss.c.required-authentication 2011-05-05 06:04:11.000000000 +0200 -+++ openssh-5.9p1/auth2-gss.c 2012-07-27 12:21:41.206602026 +0200 -@@ -163,7 +163,7 @@ input_gssapi_token(int type, u_int32_t p - } - authctxt->postponed = 0; - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); -- userauth_finish(authctxt, 0, "gssapi-with-mic"); -+ userauth_finish(authctxt, 0, "gssapi-with-mic", NULL); - } else { - if (send_tok.length != 0) { - packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN); -@@ -251,7 +251,7 @@ input_gssapi_exchange_complete(int type, - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); -- userauth_finish(authctxt, authenticated, "gssapi-with-mic"); -+ userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); - } - - static void -@@ -291,7 +291,7 @@ input_gssapi_mic(int type, u_int32_t ple - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); -- userauth_finish(authctxt, authenticated, "gssapi-with-mic"); -+ userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); - } - - Authmethod method_gssapi = { -diff -up openssh-5.9p1/auth2-chall.c.required-authentication openssh-5.9p1/auth2-chall.c ---- openssh-5.9p1/auth2-chall.c.required-authentication 2009-01-28 06:13:39.000000000 +0100 -+++ openssh-5.9p1/auth2-chall.c 2012-07-27 12:21:41.206602026 +0200 -@@ -341,7 +341,8 @@ input_userauth_info_response(int type, u - auth2_challenge_start(authctxt); - } - } -- userauth_finish(authctxt, authenticated, method); -+ userauth_finish(authctxt, authenticated, "keyboard-interactive", -+ authctxt->kbdintctxt?kbdintctxt->device->name:NULL); - xfree(method); - } - -diff -up openssh-5.9p1/auth2-none.c.required-authentication openssh-5.9p1/auth2-none.c ---- openssh-5.9p1/auth2-none.c.required-authentication 2010-06-26 02:01:33.000000000 +0200 -+++ openssh-5.9p1/auth2-none.c 2012-07-27 12:21:41.207602028 +0200 -@@ -61,7 +61,7 @@ userauth_none(Authctxt *authctxt) - { - none_enabled = 0; - packet_check_eom(); -- if (options.permit_empty_passwd && options.password_authentication) -+ if (options.permit_empty_passwd && options.password_authentication && options.required_auth2 == NULL) - return (PRIVSEP(auth_password(authctxt, ""))); - return (0); - } -diff -up openssh-5.9p1/monitor.c.required-authentication openssh-5.9p1/monitor.c ---- openssh-5.9p1/monitor.c.required-authentication 2012-07-27 12:21:41.161601930 +0200 -+++ openssh-5.9p1/monitor.c 2012-07-27 12:51:18.884927066 +0200 -@@ -199,6 +199,7 @@ static int key_blobtype = MM_NOKEY; - static char *hostbased_cuser = NULL; - static char *hostbased_chost = NULL; - static char *auth_method = "unknown"; -+static char *auth_submethod = NULL; - static u_int session_id2_len = 0; - static u_char *session_id2 = NULL; - static pid_t monitor_child_pid; -@@ -353,6 +354,7 @@ monitor_child_preauth(Authctxt *_authctx - { - struct mon_table *ent; - int authenticated = 0; -+ char **req_auth; - - debug3("preauth child monitor started"); - -@@ -367,12 +369,14 @@ monitor_child_preauth(Authctxt *_authctx - - if (compat20) { - mon_dispatch = mon_dispatch_proto20; -+ req_auth = &options.required_auth2; - - /* Permit requests for moduli and signatures */ - monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); - } else { - mon_dispatch = mon_dispatch_proto15; -+ req_auth = &options.required_auth1; - - monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); - } -@@ -380,6 +384,7 @@ monitor_child_preauth(Authctxt *_authctx - /* The first few requests do not require asynchronous access */ - while (!authenticated) { - auth_method = "unknown"; -+ auth_submethod = NULL; - authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1); - if (authenticated) { - if (!(ent->flags & MON_AUTHDECIDE)) -@@ -401,10 +406,19 @@ monitor_child_preauth(Authctxt *_authctx - } - #endif - } -+ /* Loop until the required authmethods are done */ -+ if (authenticated && *req_auth != NULL) { -+ if (auth_remove_from_list(req_auth, auth_method) == 0) -+ fatal("INTERNAL ERROR: authenticated method " -+ "\"%s\" not in required list \"%s\"", -+ auth_method, *req_auth); -+ debug2("monitor_child_preauth: required list now: %s", -+ *req_auth == NULL ? "DONE" : *req_auth); -+ } - - if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { - auth_log(authctxt, authenticated, auth_method, -- compat20 ? " ssh2" : ""); -+ auth_submethod, compat20 ? " ssh2" : ""); - if (!authenticated) - authctxt->failures++; - } -@@ -417,6 +431,8 @@ monitor_child_preauth(Authctxt *_authctx - } - } - #endif -+ if (*req_auth != NULL) -+ authenticated = 0; - } - - /* Drain any buffered messages from the child */ -@@ -862,6 +878,7 @@ mm_answer_authpassword(int sock, Buffer - auth_method = "none"; - else - auth_method = "password"; -+ auth_submethod = NULL; - - /* Causes monitor loop to terminate if authenticated */ - return (authenticated); -@@ -921,6 +938,7 @@ mm_answer_bsdauthrespond(int sock, Buffe - mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m); - - auth_method = "bsdauth"; -+ auth_submethod = NULL; - - return (authok != 0); - } -@@ -970,6 +988,7 @@ mm_answer_skeyrespond(int sock, Buffer * - mm_request_send(sock, MONITOR_ANS_SKEYRESPOND, m); - - auth_method = "skey"; -+ auth_submethod = NULL; - - return (authok != 0); - } -@@ -1059,7 +1078,8 @@ mm_answer_pam_query(int sock, Buffer *m) - xfree(prompts); - if (echo_on != NULL) - xfree(echo_on); -- auth_method = "keyboard-interactive/pam"; -+ auth_method = "keyboard-interactive"; -+ auth_submethod = "pam"; - mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m); - return (0); - } -@@ -1088,7 +1108,8 @@ mm_answer_pam_respond(int sock, Buffer * - buffer_clear(m); - buffer_put_int(m, ret); - mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m); -- auth_method = "keyboard-interactive/pam"; -+ auth_method = "keyboard-interactive"; -+ auth_submethod = "pam"; - if (ret == 0) - sshpam_authok = sshpam_ctxt; - return (0); -@@ -1102,7 +1123,8 @@ mm_answer_pam_free_ctx(int sock, Buffer - (sshpam_device.free_ctx)(sshpam_ctxt); - buffer_clear(m); - mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m); -- auth_method = "keyboard-interactive/pam"; -+ auth_method = "keyboard-interactive"; -+ auth_submethod = "pam"; - return (sshpam_authok == sshpam_ctxt); - } - #endif -@@ -1138,6 +1160,7 @@ mm_answer_keyallowed(int sock, Buffer *m - allowed = options.pubkey_authentication && - user_key_allowed(authctxt->pw, key); - auth_method = "publickey"; -+ auth_submethod = NULL; - if (options.pubkey_authentication && allowed != 1) - auth_clear_options(); - break; -@@ -1146,6 +1169,7 @@ mm_answer_keyallowed(int sock, Buffer *m - hostbased_key_allowed(authctxt->pw, - cuser, chost, key); - auth_method = "hostbased"; -+ auth_submethod = NULL; - break; - case MM_RSAHOSTKEY: - key->type = KEY_RSA1; /* XXX */ -@@ -1155,6 +1179,7 @@ mm_answer_keyallowed(int sock, Buffer *m - if (options.rhosts_rsa_authentication && allowed != 1) - auth_clear_options(); - auth_method = "rsa"; -+ auth_submethod = NULL; - break; - default: - fatal("%s: unknown key type %d", __func__, type); -@@ -1180,7 +1205,8 @@ mm_answer_keyallowed(int sock, Buffer *m - hostbased_chost = chost; - } else { - /* Log failed attempt */ -- auth_log(authctxt, 0, auth_method, compat20 ? " ssh2" : ""); -+ auth_log(authctxt, 0, auth_method, auth_submethod, -+ compat20 ? " ssh2" : ""); - xfree(blob); - xfree(cuser); - xfree(chost); -@@ -1356,6 +1382,7 @@ mm_answer_keyverify(int sock, Buffer *m) - xfree(data); - - auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased"; -+ auth_submethod = NULL; - - monitor_reset_key_state(); - -@@ -1545,6 +1572,7 @@ mm_answer_rsa_keyallowed(int sock, Buffe - debug3("%s entering", __func__); - - auth_method = "rsa"; -+ auth_submethod = NULL; - if (options.rsa_authentication && authctxt->valid) { - if ((client_n = BN_new()) == NULL) - fatal("%s: BN_new", __func__); -@@ -1650,6 +1678,7 @@ mm_answer_rsa_response(int sock, Buffer - xfree(response); - - auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa"; -+ auth_submethod = NULL; - - /* reset state */ - BN_clear_free(ssh1_challenge); -@@ -2099,6 +2128,7 @@ mm_answer_gss_userok(int sock, Buffer *m - mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); - - auth_method = "gssapi-with-mic"; -+ auth_submethod = NULL; - - /* Monitor loop will terminate if authenticated */ - return (authenticated); -@@ -2303,6 +2333,7 @@ mm_answer_jpake_check_confirm(int sock, - monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 1); - - auth_method = "jpake-01@openssh.com"; -+ auth_submethod = NULL; - return authenticated; - } - -diff -up openssh-5.9p1/servconf.c.required-authentication openssh-5.9p1/servconf.c ---- openssh-5.9p1/servconf.c.required-authentication 2012-07-27 12:21:41.167601942 +0200 -+++ openssh-5.9p1/servconf.c 2012-07-27 12:21:41.209602032 +0200 -@@ -42,6 +42,8 @@ - #include "key.h" - #include "kex.h" - #include "mac.h" -+#include "hostfile.h" -+#include "auth.h" - #include "match.h" - #include "channels.h" - #include "groupaccess.h" -@@ -129,6 +131,8 @@ initialize_server_options(ServerOptions - options->num_authkeys_files = 0; - options->num_accept_env = 0; - options->permit_tun = -1; -+ options->required_auth1 = NULL; -+ options->required_auth2 = NULL; - options->num_permitted_opens = -1; - options->adm_forced_command = NULL; - options->chroot_directory = NULL; -@@ -319,6 +323,7 @@ typedef enum { - sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, - sClientAliveCountMax, sAuthorizedKeysFile, - sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, -+ sRequiredAuthentications1, sRequiredAuthentications2, - sMatch, sPermitOpen, sForceCommand, sChrootDirectory, - sUsePrivilegeSeparation, sAllowAgentForwarding, - sZeroKnowledgePasswordAuthentication, sHostCertificate, -@@ -447,6 +452,8 @@ static struct { - { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, - { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, - { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, -+ { "requiredauthentications1", sRequiredAuthentications1, SSHCFG_ALL }, -+ { "requiredauthentications2", sRequiredAuthentications2, SSHCFG_ALL }, - { "ipqos", sIPQoS, SSHCFG_ALL }, - { NULL, sBadOption, 0 } - }; -@@ -1220,6 +1227,33 @@ process_server_config_line(ServerOptions - options->max_startups = options->max_startups_begin; - break; - -+ -+ case sRequiredAuthentications1: -+ charptr = &options->required_auth1; -+ arg = strdelim(&cp); -+ if (!arg || *arg == '\0') -+ fatal("%.200s line %d: Missing argument.", -+ filename, linenum); -+ if (auth1_check_required(arg) != 0) -+ fatal("%.200s line %d: Invalid required authentication " -+ "list", filename, linenum); -+ if (*charptr == NULL) -+ *charptr = xstrdup(arg); -+ break; -+ -+ case sRequiredAuthentications2: -+ charptr = &options->required_auth2; -+ arg = strdelim(&cp); -+ if (!arg || *arg == '\0') -+ fatal("%.200s line %d: Missing argument.", -+ filename, linenum); -+ if (auth2_check_required(arg) != 0) -+ fatal("%.200s line %d: Invalid required authentication " -+ "list", filename, linenum); -+ if (*charptr == NULL) -+ *charptr = xstrdup(arg); -+ break; -+ - case sMaxAuthTries: - intptr = &options->max_authtries; - goto parse_int; -diff -up openssh-5.9p1/servconf.h.required-authentication openssh-5.9p1/servconf.h ---- openssh-5.9p1/servconf.h.required-authentication 2011-06-23 00:30:03.000000000 +0200 -+++ openssh-5.9p1/servconf.h 2012-07-27 12:21:41.210602035 +0200 -@@ -154,6 +154,9 @@ typedef struct { - u_int num_authkeys_files; /* Files containing public keys */ - char *authorized_keys_files[MAX_AUTHKEYS_FILES]; - -+ char *required_auth1; /* Required, but not sufficient */ -+ char *required_auth2; -+ - char *adm_forced_command; - - int use_pam; /* Enable auth via PAM */ -diff -up openssh-5.9p1/sshd_config.5.required-authentication openssh-5.9p1/sshd_config.5 ---- openssh-5.9p1/sshd_config.5.required-authentication 2011-08-05 22:17:33.000000000 +0200 -+++ openssh-5.9p1/sshd_config.5 2012-07-27 12:38:47.607222070 +0200 -@@ -723,6 +723,8 @@ Available keywords are - .Cm PermitOpen , - .Cm PermitRootLogin , - .Cm PermitTunnel , -+.Cm RequiredAuthentications1, -+.Cm RequiredAuthentications2, - .Cm PubkeyAuthentication , - .Cm RhostsRSAAuthentication , - .Cm RSAAuthentication , -@@ -920,6 +922,21 @@ Specifies a list of revoked public keys. - Keys listed in this file will be refused for public key authentication. - Note that if this file is not readable, then public key authentication will - be refused for all users. -+.It Cm RequiredAuthentications[12] -+ Specifies required methods of authentications that has to succeed before authorizing the connection. -+ (RequiredAuthentication1 for Protocol version 1, and RequiredAuthentication2 for v2) -+ -+ RequiredAuthentications1 method[,method...] -+ RequiredAuthentications2 method[,method...] -+ -+.Pp -+Example 1: -+ -+ RequiredAuthentications2 password,hostbased -+ -+Example 2: -+ RequiredAuthentications2 publickey,password -+ - .It Cm RhostsRSAAuthentication - Specifies whether rhosts or /etc/hosts.equiv authentication together - with successful RSA host authentication is allowed. diff --git a/openssh-5.9p1-vendor.patch b/openssh-5.9p1-vendor.patch deleted file mode 100644 index 1413fa6..0000000 --- a/openssh-5.9p1-vendor.patch +++ /dev/null @@ -1,157 +0,0 @@ -diff -up openssh-5.9p1/configure.ac.vendor openssh-5.9p1/configure.ac ---- openssh-5.9p1/configure.ac.vendor 2012-02-06 17:35:37.439855272 +0100 -+++ openssh-5.9p1/configure.ac 2012-02-06 17:35:37.510219862 +0100 -@@ -4135,6 +4135,12 @@ AC_ARG_WITH([lastlog], - fi - ] - ) -+AC_ARG_ENABLE(vendor-patchlevel, -+ [ --enable-vendor-patchlevel=TAG specify a vendor patch level], -+ [AC_DEFINE_UNQUOTED(SSH_VENDOR_PATCHLEVEL,[SSH_RELEASE "-" "$enableval"],[Define to your vendor patch level, if it has been modified from the upstream source release.]) -+ SSH_VENDOR_PATCHLEVEL="$enableval"], -+ [AC_DEFINE(SSH_VENDOR_PATCHLEVEL,SSH_RELEASE,[Define to your vendor patch level, if it has been modified from the upstream source release.]) -+ SSH_VENDOR_PATCHLEVEL=none]) - - dnl lastlog, [uw]tmpx? detection - dnl NOTE: set the paths in the platform section to avoid the -@@ -4361,6 +4367,7 @@ echo " Translate v4 in v6 hack - echo " BSD Auth support: $BSD_AUTH_MSG" - echo " Random number source: $RAND_MSG" - echo " Privsep sandbox style: $SANDBOX_STYLE" -+echo " Vendor patch level: $SSH_VENDOR_PATCHLEVEL" - - echo "" - -diff -up openssh-5.9p1/servconf.c.vendor openssh-5.9p1/servconf.c ---- openssh-5.9p1/servconf.c.vendor 2012-02-06 17:35:37.432972267 +0100 -+++ openssh-5.9p1/servconf.c 2012-02-06 17:37:58.806272833 +0100 -@@ -125,6 +125,7 @@ initialize_server_options(ServerOptions - options->max_authtries = -1; - options->max_sessions = -1; - options->banner = NULL; -+ options->show_patchlevel = -1; - options->use_dns = -1; - options->client_alive_interval = -1; - options->client_alive_count_max = -1; -@@ -283,6 +284,8 @@ fill_default_server_options(ServerOption - options->ip_qos_interactive = IPTOS_LOWDELAY; - if (options->ip_qos_bulk == -1) - options->ip_qos_bulk = IPTOS_THROUGHPUT; -+ if (options->show_patchlevel == -1) -+ options->show_patchlevel = 0; - - /* Turn privilege separation on by default */ - if (use_privsep == -1) -@@ -321,7 +324,7 @@ typedef enum { - sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, - sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, - sMaxStartups, sMaxAuthTries, sMaxSessions, -- sBanner, sUseDNS, sHostbasedAuthentication, -+ sBanner, sShowPatchLevel, sUseDNS, sHostbasedAuthentication, - sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, - sClientAliveCountMax, sAuthorizedKeysFile, - sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, -@@ -436,6 +439,7 @@ static struct { - { "maxauthtries", sMaxAuthTries, SSHCFG_ALL }, - { "maxsessions", sMaxSessions, SSHCFG_ALL }, - { "banner", sBanner, SSHCFG_ALL }, -+ { "showpatchlevel", sShowPatchLevel, SSHCFG_GLOBAL }, - { "usedns", sUseDNS, SSHCFG_GLOBAL }, - { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL }, - { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL }, -@@ -1092,6 +1096,10 @@ process_server_config_line(ServerOptions - multistate_ptr = multistate_privsep; - goto parse_multistate; - -+ case sShowPatchLevel: -+ intptr = &options->show_patchlevel; -+ goto parse_flag; -+ - case sAllowUsers: - while ((arg = strdelim(&cp)) && *arg != '\0') { - if (options->num_allow_users >= MAX_ALLOW_USERS) -@@ -1807,6 +1815,7 @@ dump_config(ServerOptions *o) - dump_cfg_fmtint(sUseLogin, o->use_login); - dump_cfg_fmtint(sCompression, o->compression); - dump_cfg_fmtint(sGatewayPorts, o->gateway_ports); -+ dump_cfg_fmtint(sShowPatchLevel, o->show_patchlevel); - dump_cfg_fmtint(sUseDNS, o->use_dns); - dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); - dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); -diff -up openssh-5.9p1/servconf.h.vendor openssh-5.9p1/servconf.h ---- openssh-5.9p1/servconf.h.vendor 2012-02-06 17:35:37.434095467 +0100 -+++ openssh-5.9p1/servconf.h 2012-02-06 17:35:37.512225786 +0100 -@@ -140,6 +140,7 @@ typedef struct { - int max_authtries; - int max_sessions; - char *banner; /* SSH-2 banner message */ -+ int show_patchlevel; /* Show vendor patch level to clients */ - int use_dns; - int client_alive_interval; /* - * poke the client this often to -diff -up openssh-5.9p1/sshd_config.vendor openssh-5.9p1/sshd_config ---- openssh-5.9p1/sshd_config.vendor 2012-02-06 17:35:37.499226201 +0100 -+++ openssh-5.9p1/sshd_config 2012-02-06 17:35:37.515220444 +0100 -@@ -112,6 +112,7 @@ X11Forwarding yes - #Compression delayed - #ClientAliveInterval 0 - #ClientAliveCountMax 3 -+#ShowPatchLevel no - #UseDNS yes - #PidFile /var/run/sshd.pid - #MaxStartups 10 -diff -up openssh-5.9p1/sshd_config.0.vendor openssh-5.9p1/sshd_config.0 ---- openssh-5.9p1/sshd_config.0.vendor 2012-02-06 17:35:37.500225787 +0100 -+++ openssh-5.9p1/sshd_config.0 2012-02-06 17:35:37.513225808 +0100 -@@ -556,6 +556,11 @@ DESCRIPTION - Defines the number of bits in the ephemeral protocol version 1 - server key. The minimum value is 512, and the default is 1024. - -+ ShowPatchLevel -+ Specifies whether sshd will display the specific patch level of -+ the binary in the server identification string. The patch level -+ is set at compile-time. The default is M-bM-^@M-^\noM-bM-^@M-^]. -+ - StrictModes - Specifies whether sshd(8) should check file modes and ownership - of the user's files and home directory before accepting login. -diff -up openssh-5.9p1/sshd_config.5.vendor openssh-5.9p1/sshd_config.5 ---- openssh-5.9p1/sshd_config.5.vendor 2012-02-06 17:35:37.500225787 +0100 -+++ openssh-5.9p1/sshd_config.5 2012-02-06 17:35:37.514220449 +0100 -@@ -982,6 +982,14 @@ This option applies to protocol version - .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. -+.It Cm ShowPatchLevel -+Specifies whether -+.Nm sshd -+will display the patch level of the binary in the identification string. -+The patch level is set at compile-time. -+The default is -+.Dq no . -+This option applies to protocol version 1 only. - .It Cm StrictModes - Specifies whether - .Xr sshd 8 -diff -up openssh-5.9p1/sshd.c.vendor openssh-5.9p1/sshd.c ---- openssh-5.9p1/sshd.c.vendor 2012-02-06 17:35:37.485230832 +0100 -+++ openssh-5.9p1/sshd.c 2012-02-06 17:35:37.513225808 +0100 -@@ -431,7 +431,7 @@ sshd_exchange_identification(int sock_in - minor = PROTOCOL_MINOR_1; - } - snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor, -- SSH_VERSION, newline); -+ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION, newline); - server_version_string = xstrdup(buf); - - /* Send our protocol version identification. */ -@@ -1634,7 +1634,8 @@ main(int ac, char **av) - exit(1); - } - -- debug("sshd version %.100s", SSH_RELEASE); -+ debug("sshd version %.100s", -+ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_RELEASE); - - /* Store privilege separation user for later use if required. */ - if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { diff --git a/openssh-6.0p1-gsskex.patch b/openssh-6.0p1-gsskex.patch deleted file mode 100644 index be2aed2..0000000 --- a/openssh-6.0p1-gsskex.patch +++ /dev/null @@ -1,3025 +0,0 @@ -diff -up openssh-6.0p1/auth2.c.gsskex openssh-6.0p1/auth2.c ---- openssh-6.0p1/auth2.c.gsskex 2012-09-12 15:32:19.110689080 +0200 -+++ openssh-6.0p1/auth2.c 2012-09-12 15:32:28.309651601 +0200 -@@ -69,6 +69,7 @@ extern Authmethod method_passwd; - extern Authmethod method_kbdint; - extern Authmethod method_hostbased; - #ifdef GSSAPI -+extern Authmethod method_gsskeyex; - extern Authmethod method_gssapi; - #endif - #ifdef JPAKE -@@ -79,6 +80,7 @@ Authmethod *authmethods[] = { - &method_none, - &method_pubkey, - #ifdef GSSAPI -+ &method_gsskeyex, - &method_gssapi, - #endif - #ifdef JPAKE -diff -up openssh-6.0p1/auth2-gss.c.gsskex openssh-6.0p1/auth2-gss.c ---- openssh-6.0p1/auth2-gss.c.gsskex 2012-09-12 15:32:19.126689015 +0200 -+++ openssh-6.0p1/auth2-gss.c 2012-09-12 15:32:28.309651601 +0200 -@@ -52,6 +52,40 @@ static void input_gssapi_mic(int type, u - static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); - static void input_gssapi_errtok(int, u_int32_t, void *); - -+/* -+ * The 'gssapi_keyex' userauth mechanism. -+ */ -+static int -+userauth_gsskeyex(Authctxt *authctxt) -+{ -+ int authenticated = 0; -+ Buffer b; -+ gss_buffer_desc mic, gssbuf; -+ u_int len; -+ -+ mic.value = packet_get_string(&len); -+ mic.length = len; -+ -+ packet_check_eom(); -+ -+ ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service, -+ "gssapi-keyex"); -+ -+ gssbuf.value = buffer_ptr(&b); -+ gssbuf.length = buffer_len(&b); -+ -+ /* gss_kex_context is NULL with privsep, so we can't check it here */ -+ if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, -+ &gssbuf, &mic)))) -+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, -+ authctxt->pw)); -+ -+ buffer_free(&b); -+ xfree(mic.value); -+ -+ return (authenticated); -+} -+ - /* - * We only support those mechanisms that we know about (ie ones that we know - * how to check local user kuserok and the like) -@@ -244,7 +278,8 @@ input_gssapi_exchange_complete(int type, - - packet_check_eom(); - -- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); -+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, -+ authctxt->pw)); - - authctxt->postponed = 0; - dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); -@@ -286,7 +321,8 @@ input_gssapi_mic(int type, u_int32_t ple - gssbuf.length = buffer_len(&b); - - if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) -- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); -+ authenticated = -+ PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw)); - else - logit("GSSAPI MIC check failed"); - -@@ -303,6 +339,12 @@ input_gssapi_mic(int type, u_int32_t ple - userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); - } - -+Authmethod method_gsskeyex = { -+ "gssapi-keyex", -+ userauth_gsskeyex, -+ &options.gss_authentication -+}; -+ - Authmethod method_gssapi = { - "gssapi-with-mic", - userauth_gssapi, -diff -up openssh-6.0p1/auth-krb5.c.gsskex openssh-6.0p1/auth-krb5.c ---- openssh-6.0p1/auth-krb5.c.gsskex 2012-09-12 15:32:19.118689046 +0200 -+++ openssh-6.0p1/auth-krb5.c 2012-09-12 16:03:22.216097657 +0200 -@@ -50,6 +50,7 @@ - #include - #include - #include -+#include - #include - - extern ServerOptions options; -@@ -170,8 +171,13 @@ auth_krb5_password(Authctxt *authctxt, c - - len = strlen(authctxt->krb5_ticket_file) + 6; - authctxt->krb5_ccname = xmalloc(len); -- snprintf(authctxt->krb5_ccname, len, "FILE:%s", -+#ifdef USE_CCAPI -+ snprintf(authctxt->krb5_ccname, len, "API:%s", - authctxt->krb5_ticket_file); -+#else -+ snprintf(authctxt->krb5_ccname, len, "DIR:%s", -+ authctxt->krb5_ticket_file); -+#endif - - #ifdef USE_PAM - if (options.use_pam) -@@ -208,10 +214,33 @@ auth_krb5_password(Authctxt *authctxt, c - void - krb5_cleanup_proc(Authctxt *authctxt) - { -+ struct stat krb5_ccname_stat; -+ char krb5_ccname[128], *krb5_ccname_dir_end; -+ - debug("krb5_cleanup_proc called"); - if (authctxt->krb5_fwd_ccache) { - krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); - authctxt->krb5_fwd_ccache = NULL; -+ -+ /* assume ticket cache type DIR - DIR::/tmp/krb5cc_876600005_T9eDKSQvzb/tkt */ -+ strncpy(krb5_ccname, authctxt->krb5_ccname + strlen("DIR::"), sizeof(krb5_ccname) - 10); -+ -+ krb5_ccname_dir_end = strrchr(krb5_ccname, '/'); -+ if (krb5_ccname_dir_end != NULL) { -+ strcpy(krb5_ccname_dir_end, "/primary"); -+ -+ if (stat(krb5_ccname, &krb5_ccname_stat) == 0) { -+ if (unlink(krb5_ccname) == 0) { -+ *krb5_ccname_dir_end = '\0'; -+ if (rmdir(krb5_ccname) == -1) -+ debug("cache dir '%s' remove failed: %s", krb5_ccname, strerror(errno)); -+ } -+ else -+ debug("cache primary file '%s', remove failed: %s", -+ krb5_ccname, strerror(errno) -+ ); -+ } -+ } - } - if (authctxt->krb5_user) { - krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user); -@@ -226,29 +255,35 @@ krb5_cleanup_proc(Authctxt *authctxt) - #ifndef HEIMDAL - krb5_error_code - ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { -- int tmpfd, ret; -+ int ret; - char ccname[40]; - mode_t old_umask; -+#ifdef USE_CCAPI -+ char cctemplate[] = "API:krb5cc_%d"; -+#else -+ char cctemplate[] = "DIR:/tmp/krb5cc_%d_XXXXXXXXXX"; -+ char *tmpdir; -+#endif - - ret = snprintf(ccname, sizeof(ccname), -- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); -+ cctemplate, geteuid()); - if (ret < 0 || (size_t)ret >= sizeof(ccname)) - return ENOMEM; - -- old_umask = umask(0177); -- tmpfd = mkstemp(ccname + strlen("FILE:")); -+#ifndef USE_CCAPI -+ old_umask = umask(0077); -+ tmpdir = mkdtemp(ccname + strlen("DIR:")); - umask(old_umask); -- if (tmpfd == -1) { -- logit("mkstemp(): %.100s", strerror(errno)); -+ if (tmpdir == NULL) { -+ logit("mkdtemp(): %.100s", strerror(errno)); - return errno; - } -- -- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { -- logit("fchmod(): %.100s", strerror(errno)); -- close(tmpfd); -+ if (chmod(tmpdir, S_IRUSR | S_IWUSR | S_IXUSR) == -1) { -+ logit("chmod(): %.100s", strerror(errno)); - return errno; - } -- close(tmpfd); -+ -+#endif - - return (krb5_cc_resolve(ctx, ccname, ccache)); - } -diff -up openssh-6.0p1/ChangeLog.gssapi.gsskex openssh-6.0p1/ChangeLog.gssapi ---- openssh-6.0p1/ChangeLog.gssapi.gsskex 2012-09-12 15:32:19.106689094 +0200 -+++ openssh-6.0p1/ChangeLog.gssapi 2012-09-12 15:32:28.310651598 +0200 -@@ -0,0 +1,113 @@ -+20110101 -+ - Finally update for OpenSSH 5.6p1 -+ - Add GSSAPIServerIdentity option from Jim Basney -+ -+20100308 -+ - [ Makefile.in, key.c, key.h ] -+ Updates for OpenSSH 5.4p1 -+ - [ servconf.c ] -+ Include GSSAPI options in the sshd -T configuration dump, and flag -+ some older configuration options as being unsupported. Thanks to Colin -+ Watson. -+ - -+ -+20100124 -+ - [ sshconnect2.c ] -+ Adapt to deal with additional element in Authmethod structure. Thanks to -+ Colin Watson -+ -+20090615 -+ - [ gss-genr.c gss-serv.c kexgssc.c kexgsss.c monitor.c sshconnect2.c -+ sshd.c ] -+ Fix issues identified by Greg Hudson following a code review -+ Check return value of gss_indicate_mechs -+ Protect GSSAPI calls in monitor, so they can only be used if enabled -+ Check return values of bignum functions in key exchange -+ Use BN_clear_free to clear other side's DH value -+ Make ssh_gssapi_id_kex more robust -+ Only configure kex table pointers if GSSAPI is enabled -+ Don't leak mechanism list, or gss mechanism list -+ Cast data.length before printing -+ If serverkey isn't provided, use an empty string, rather than NULL -+ -+20090201 -+ - [ gss-genr.c gss-serv.c kex.h kexgssc.c readconf.c readconf.h ssh-gss.h -+ ssh_config.5 sshconnet2.c ] -+ Add support for the GSSAPIClientIdentity option, which allows the user -+ to specify which GSSAPI identity to use to contact a given server -+ -+20080404 -+ - [ gss-serv.c ] -+ Add code to actually implement GSSAPIStrictAcceptCheck, which had somehow -+ been omitted from a previous version of this patch. Reported by Borislav -+ Stoichkov -+ -+20070317 -+ - [ gss-serv-krb5.c ] -+ Remove C99ism, where new_ccname was being declared in the middle of a -+ function -+ -+20061220 -+ - [ servconf.c ] -+ Make default for GSSAPIStrictAcceptorCheck be Yes, to match previous, and -+ documented, behaviour. Reported by Dan Watson. -+ -+20060910 -+ - [ gss-genr.c kexgssc.c kexgsss.c kex.h monitor.c sshconnect2.c sshd.c -+ ssh-gss.h ] -+ add support for gss-group14-sha1 key exchange mechanisms -+ - [ gss-serv.c servconf.c servconf.h sshd_config sshd_config.5 ] -+ Add GSSAPIStrictAcceptorCheck option to allow the disabling of -+ acceptor principal checking on multi-homed machines. -+ -+ - [ sshd_config ssh_config ] -+ Add settings for GSSAPIKeyExchange and GSSAPITrustDNS to the sample -+ configuration files -+ - [ kexgss.c kegsss.c sshconnect2.c sshd.c ] -+ Code cleanup. Replace strlen/xmalloc/snprintf sequences with xasprintf() -+ Limit length of error messages displayed by client -+ -+20060909 -+ - [ gss-genr.c gss-serv.c ] -+ move ssh_gssapi_acquire_cred() and ssh_gssapi_server_ctx to be server -+ only, where they belong -+ -+ -+20060829 -+ - [ gss-serv-krb5.c ] -+ Fix CCAPI credentials cache name when creating KRB5CCNAME environment -+ variable -+ -+20060828 -+ - [ gss-genr.c ] -+ Avoid Heimdal context freeing problem -+ -+ -+20060818 -+ - [ gss-genr.c ssh-gss.h sshconnect2.c ] -+ Make sure that SPENGO is disabled -+ -+ -+20060421 -+ - [ gssgenr.c, sshconnect2.c ] -+ a few type changes (signed versus unsigned, int versus size_t) to -+ fix compiler errors/warnings -+ (from jbasney AT ncsa.uiuc.edu) -+ - [ kexgssc.c, sshconnect2.c ] -+ fix uninitialized variable warnings -+ (from jbasney AT ncsa.uiuc.edu) -+ - [ gssgenr.c ] -+ pass oid to gss_display_status (helpful when using GSSAPI mechglue) -+ (from jbasney AT ncsa.uiuc.edu) -+ -+ - [ gss-serv-krb5.c ] -+ #ifdef HAVE_GSSAPI_KRB5 should be #ifdef HAVE_GSSAPI_KRB5_H -+ (from jbasney AT ncsa.uiuc.edu) -+ -+ - [ readconf.c, readconf.h, ssh_config.5, sshconnect2.c -+ add client-side GssapiKeyExchange option -+ (from jbasney AT ncsa.uiuc.edu) -+ - [ sshconnect2.c ] -+ add support for GssapiTrustDns option for gssapi-with-mic -+ (from jbasney AT ncsa.uiuc.edu) -+ -diff -up openssh-6.0p1/clientloop.c.gsskex openssh-6.0p1/clientloop.c ---- openssh-6.0p1/clientloop.c.gsskex 2012-09-12 15:32:19.113689067 +0200 -+++ openssh-6.0p1/clientloop.c 2012-09-12 15:32:28.311651595 +0200 -@@ -111,6 +111,10 @@ - #include "msg.h" - #include "roaming.h" - -+#ifdef GSSAPI -+#include "ssh-gss.h" -+#endif -+ - /* import options */ - extern Options options; - -@@ -1540,6 +1544,15 @@ client_loop(int have_pty, int escape_cha - /* Do channel operations unless rekeying in progress. */ - if (!rekeying) { - channel_after_select(readset, writeset); -+ -+#ifdef GSSAPI -+ if (options.gss_renewal_rekey && -+ ssh_gssapi_credentials_updated(GSS_C_NO_CONTEXT)) { -+ debug("credentials updated - forcing rekey"); -+ need_rekeying = 1; -+ } -+#endif -+ - if (need_rekeying || packet_need_rekeying()) { - debug("need rekeying"); - xxx_kex->done = 0; -diff -up openssh-6.0p1/configure.ac.gsskex openssh-6.0p1/configure.ac ---- openssh-6.0p1/configure.ac.gsskex 2012-09-12 15:32:19.085689183 +0200 -+++ openssh-6.0p1/configure.ac 2012-09-12 15:32:28.312651591 +0200 -@@ -545,6 +545,30 @@ main() { if (NSVersionOfRunTimeLibrary(" - [Use tunnel device compatibility to OpenBSD]) - AC_DEFINE([SSH_TUN_PREPEND_AF], [1], - [Prepend the address family to IP tunnel traffic]) -+ AC_MSG_CHECKING(if we have the Security Authorization Session API) -+ AC_TRY_COMPILE([#include ], -+ [SessionCreate(0, 0);], -+ [ac_cv_use_security_session_api="yes" -+ AC_DEFINE(USE_SECURITY_SESSION_API, 1, -+ [platform has the Security Authorization Session API]) -+ LIBS="$LIBS -framework Security" -+ AC_MSG_RESULT(yes)], -+ [ac_cv_use_security_session_api="no" -+ AC_MSG_RESULT(no)]) -+ AC_MSG_CHECKING(if we have an in-memory credentials cache) -+ AC_TRY_COMPILE( -+ [#include ], -+ [cc_context_t c; -+ (void) cc_initialize (&c, 0, NULL, NULL);], -+ [AC_DEFINE(USE_CCAPI, 1, -+ [platform uses an in-memory credentials cache]) -+ LIBS="$LIBS -framework Security" -+ AC_MSG_RESULT(yes) -+ if test "x$ac_cv_use_security_session_api" = "xno"; then -+ AC_MSG_ERROR(*** Need a security framework to use the credentials cache API ***) -+ fi], -+ [AC_MSG_RESULT(no)] -+ ) - m4_pattern_allow([AU_IPv]) - AC_CHECK_DECL([AU_IPv4], [], - AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) -diff -up openssh-6.0p1/gss-genr.c.gsskex openssh-6.0p1/gss-genr.c ---- openssh-6.0p1/gss-genr.c.gsskex 2012-09-12 15:32:19.097689132 +0200 -+++ openssh-6.0p1/gss-genr.c 2012-09-12 15:32:28.313651587 +0200 -@@ -1,7 +1,7 @@ - /* $OpenBSD: gss-genr.c,v 1.20 2009/06/22 05:39:28 dtucker Exp $ */ - - /* -- * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions -@@ -39,12 +39,167 @@ - #include "buffer.h" - #include "log.h" - #include "ssh2.h" -+#include "cipher.h" -+#include "key.h" -+#include "kex.h" -+#include - - #include "ssh-gss.h" - - extern u_char *session_id2; - extern u_int session_id2_len; - -+typedef struct { -+ char *encoded; -+ gss_OID oid; -+} ssh_gss_kex_mapping; -+ -+/* -+ * XXX - It would be nice to find a more elegant way of handling the -+ * XXX passing of the key exchange context to the userauth routines -+ */ -+ -+Gssctxt *gss_kex_context = NULL; -+ -+static ssh_gss_kex_mapping *gss_enc2oid = NULL; -+ -+int -+ssh_gssapi_oid_table_ok() { -+ return (gss_enc2oid != NULL); -+} -+ -+/* -+ * Return a list of the gss-group1-sha1 mechanisms supported by this program -+ * -+ * We test mechanisms to ensure that we can use them, to avoid starting -+ * a key exchange with a bad mechanism -+ */ -+ -+char * -+ssh_gssapi_client_mechanisms(const char *host, const char *client) { -+ gss_OID_set gss_supported; -+ OM_uint32 min_status; -+ -+ if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported))) -+ return NULL; -+ -+ return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, -+ host, client)); -+} -+ -+char * -+ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, -+ const char *host, const char *client) { -+ Buffer buf; -+ size_t i; -+ int oidpos, enclen; -+ char *mechs, *encoded; -+ u_char digest[EVP_MAX_MD_SIZE]; -+ char deroid[2]; -+ const EVP_MD *evp_md = EVP_md5(); -+ EVP_MD_CTX md; -+ -+ if (gss_enc2oid != NULL) { -+ for (i = 0; gss_enc2oid[i].encoded != NULL; i++) -+ xfree(gss_enc2oid[i].encoded); -+ xfree(gss_enc2oid); -+ } -+ -+ gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) * -+ (gss_supported->count + 1)); -+ -+ buffer_init(&buf); -+ -+ oidpos = 0; -+ for (i = 0; i < gss_supported->count; i++) { -+ if (gss_supported->elements[i].length < 128 && -+ (*check)(NULL, &(gss_supported->elements[i]), host, client)) { -+ -+ deroid[0] = SSH_GSS_OIDTYPE; -+ deroid[1] = gss_supported->elements[i].length; -+ -+ EVP_DigestInit(&md, evp_md); -+ EVP_DigestUpdate(&md, deroid, 2); -+ EVP_DigestUpdate(&md, -+ gss_supported->elements[i].elements, -+ gss_supported->elements[i].length); -+ EVP_DigestFinal(&md, digest, NULL); -+ -+ encoded = xmalloc(EVP_MD_size(evp_md) * 2); -+ enclen = __b64_ntop(digest, EVP_MD_size(evp_md), -+ encoded, EVP_MD_size(evp_md) * 2); -+ -+ if (oidpos != 0) -+ buffer_put_char(&buf, ','); -+ -+ buffer_append(&buf, KEX_GSS_GEX_SHA1_ID, -+ sizeof(KEX_GSS_GEX_SHA1_ID) - 1); -+ buffer_append(&buf, encoded, enclen); -+ buffer_put_char(&buf, ','); -+ buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID, -+ sizeof(KEX_GSS_GRP1_SHA1_ID) - 1); -+ buffer_append(&buf, encoded, enclen); -+ buffer_put_char(&buf, ','); -+ buffer_append(&buf, KEX_GSS_GRP14_SHA1_ID, -+ sizeof(KEX_GSS_GRP14_SHA1_ID) - 1); -+ buffer_append(&buf, encoded, enclen); -+ -+ gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]); -+ gss_enc2oid[oidpos].encoded = encoded; -+ oidpos++; -+ } -+ } -+ gss_enc2oid[oidpos].oid = NULL; -+ gss_enc2oid[oidpos].encoded = NULL; -+ -+ buffer_put_char(&buf, '\0'); -+ -+ mechs = xmalloc(buffer_len(&buf)); -+ buffer_get(&buf, mechs, buffer_len(&buf)); -+ buffer_free(&buf); -+ -+ if (strlen(mechs) == 0) { -+ xfree(mechs); -+ mechs = NULL; -+ } -+ -+ return (mechs); -+} -+ -+gss_OID -+ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) { -+ int i = 0; -+ -+ switch (kex_type) { -+ case KEX_GSS_GRP1_SHA1: -+ if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID)) -+ return GSS_C_NO_OID; -+ name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1; -+ break; -+ case KEX_GSS_GRP14_SHA1: -+ if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID)) -+ return GSS_C_NO_OID; -+ name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1; -+ break; -+ case KEX_GSS_GEX_SHA1: -+ if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID)) -+ return GSS_C_NO_OID; -+ name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1; -+ break; -+ default: -+ return GSS_C_NO_OID; -+ } -+ -+ while (gss_enc2oid[i].encoded != NULL && -+ strcmp(name, gss_enc2oid[i].encoded) != 0) -+ i++; -+ -+ if (gss_enc2oid[i].oid != NULL && ctx != NULL) -+ ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid); -+ -+ return gss_enc2oid[i].oid; -+} -+ - /* Check that the OID in a data stream matches that in the context */ - int - ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) -@@ -197,7 +352,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int de - } - - ctx->major = gss_init_sec_context(&ctx->minor, -- GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid, -+ ctx->client_creds, &ctx->context, ctx->name, ctx->oid, - GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, - 0, NULL, recv_tok, NULL, send_tok, flags, NULL); - -@@ -227,8 +382,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, con - } - - OM_uint32 -+ssh_gssapi_client_identity(Gssctxt *ctx, const char *name) -+{ -+ gss_buffer_desc gssbuf; -+ gss_name_t gssname; -+ OM_uint32 status; -+ gss_OID_set oidset; -+ -+ gssbuf.value = (void *) name; -+ gssbuf.length = strlen(gssbuf.value); -+ -+ gss_create_empty_oid_set(&status, &oidset); -+ gss_add_oid_set_member(&status, ctx->oid, &oidset); -+ -+ ctx->major = gss_import_name(&ctx->minor, &gssbuf, -+ GSS_C_NT_USER_NAME, &gssname); -+ -+ if (!ctx->major) -+ ctx->major = gss_acquire_cred(&ctx->minor, -+ gssname, 0, oidset, GSS_C_INITIATE, -+ &ctx->client_creds, NULL, NULL); -+ -+ gss_release_name(&status, &gssname); -+ gss_release_oid_set(&status, &oidset); -+ -+ if (ctx->major) -+ ssh_gssapi_error(ctx); -+ -+ return(ctx->major); -+} -+ -+OM_uint32 - ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) - { -+ if (ctx == NULL) -+ return -1; -+ - if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, - GSS_C_QOP_DEFAULT, buffer, hash))) - ssh_gssapi_error(ctx); -@@ -236,6 +425,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer - return (ctx->major); - } - -+/* Priviledged when used by server */ -+OM_uint32 -+ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) -+{ -+ if (ctx == NULL) -+ return -1; -+ -+ ctx->major = gss_verify_mic(&ctx->minor, ctx->context, -+ gssbuf, gssmic, NULL); -+ -+ return (ctx->major); -+} -+ - void - ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, - const char *context) -@@ -249,11 +451,16 @@ ssh_gssapi_buildmic(Buffer *b, const cha - } - - int --ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) -+ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, -+ const char *client) - { - gss_buffer_desc token = GSS_C_EMPTY_BUFFER; - OM_uint32 major, minor; - gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"}; -+ Gssctxt *intctx = NULL; -+ -+ if (ctx == NULL) -+ ctx = &intctx; - - /* RFC 4462 says we MUST NOT do SPNEGO */ - if (oid->length == spnego_oid.length && -@@ -263,6 +470,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx - ssh_gssapi_build_ctx(ctx); - ssh_gssapi_set_oid(*ctx, oid); - major = ssh_gssapi_import_name(*ctx, host); -+ -+ if (!GSS_ERROR(major) && client) -+ major = ssh_gssapi_client_identity(*ctx, client); -+ - if (!GSS_ERROR(major)) { - major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, - NULL); -@@ -272,10 +483,67 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx - GSS_C_NO_BUFFER); - } - -- if (GSS_ERROR(major)) -+ if (GSS_ERROR(major) || intctx != NULL) - ssh_gssapi_delete_ctx(ctx); - - return (!GSS_ERROR(major)); - } - -+int -+ssh_gssapi_credentials_updated(Gssctxt *ctxt) { -+ static gss_name_t saved_name = GSS_C_NO_NAME; -+ static OM_uint32 saved_lifetime = 0; -+ static gss_OID saved_mech = GSS_C_NO_OID; -+ static gss_name_t name; -+ static OM_uint32 last_call = 0; -+ OM_uint32 lifetime, now, major, minor; -+ int equal; -+ gss_cred_usage_t usage = GSS_C_INITIATE; -+ -+ now = time(NULL); -+ -+ if (ctxt) { -+ debug("Rekey has happened - updating saved versions"); -+ -+ if (saved_name != GSS_C_NO_NAME) -+ gss_release_name(&minor, &saved_name); -+ -+ major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, -+ &saved_name, &saved_lifetime, NULL, NULL); -+ -+ if (!GSS_ERROR(major)) { -+ saved_mech = ctxt->oid; -+ saved_lifetime+= now; -+ } else { -+ /* Handle the error */ -+ } -+ return 0; -+ } -+ -+ if (now - last_call < 10) -+ return 0; -+ -+ last_call = now; -+ -+ if (saved_mech == GSS_C_NO_OID) -+ return 0; -+ -+ major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, -+ &name, &lifetime, NULL, NULL); -+ if (major == GSS_S_CREDENTIALS_EXPIRED) -+ return 0; -+ else if (GSS_ERROR(major)) -+ return 0; -+ -+ major = gss_compare_name(&minor, saved_name, name, &equal); -+ gss_release_name(&minor, &name); -+ if (GSS_ERROR(major)) -+ return 0; -+ -+ if (equal && (saved_lifetime < lifetime + now - 10)) -+ return 1; -+ -+ return 0; -+} -+ - #endif /* GSSAPI */ -diff -up openssh-6.0p1/gss-serv.c.gsskex openssh-6.0p1/gss-serv.c ---- openssh-6.0p1/gss-serv.c.gsskex 2012-09-12 15:32:19.123689027 +0200 -+++ openssh-6.0p1/gss-serv.c 2012-09-12 15:53:27.719520213 +0200 -@@ -45,15 +45,20 @@ - #include "channels.h" - #include "session.h" - #include "misc.h" -+#include "servconf.h" -+#include "uidswap.h" - - #include "ssh-gss.h" -+#include "monitor_wrap.h" -+ -+extern ServerOptions options; - - static ssh_gssapi_client gssapi_client = - { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, -- GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL}}; -+ GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, NULL, {NULL, NULL, NULL}, 0, 0}; - - ssh_gssapi_mech gssapi_null_mech = -- { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL}; -+ { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL}; - - #ifdef KRB5 - extern ssh_gssapi_mech gssapi_kerberos_mech; -@@ -81,25 +86,32 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx) - char lname[MAXHOSTNAMELEN]; - gss_OID_set oidset; - -- gss_create_empty_oid_set(&status, &oidset); -- gss_add_oid_set_member(&status, ctx->oid, &oidset); -+ if (options.gss_strict_acceptor) { -+ gss_create_empty_oid_set(&status, &oidset); -+ gss_add_oid_set_member(&status, ctx->oid, &oidset); -+ -+ if (gethostname(lname, MAXHOSTNAMELEN)) { -+ gss_release_oid_set(&status, &oidset); -+ return (-1); -+ } - -- if (gethostname(lname, MAXHOSTNAMELEN)) { -- gss_release_oid_set(&status, &oidset); -- return (-1); -- } -+ if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { -+ gss_release_oid_set(&status, &oidset); -+ return (ctx->major); -+ } -+ -+ if ((ctx->major = gss_acquire_cred(&ctx->minor, -+ ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, -+ NULL, NULL))) -+ ssh_gssapi_error(ctx); - -- if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { - gss_release_oid_set(&status, &oidset); - return (ctx->major); -+ } else { -+ ctx->name = GSS_C_NO_NAME; -+ ctx->creds = GSS_C_NO_CREDENTIAL; - } -- -- if ((ctx->major = gss_acquire_cred(&ctx->minor, -- ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL))) -- ssh_gssapi_error(ctx); -- -- gss_release_oid_set(&status, &oidset); -- return (ctx->major); -+ return GSS_S_COMPLETE; - } - - /* Privileged */ -@@ -114,6 +126,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss - } - - /* Unprivileged */ -+char * -+ssh_gssapi_server_mechanisms() { -+ gss_OID_set supported; -+ -+ ssh_gssapi_supported_oids(&supported); -+ return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech, -+ NULL, NULL)); -+} -+ -+/* Unprivileged */ -+int -+ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data, -+ const char *dummy) { -+ Gssctxt *ctx = NULL; -+ int res; -+ -+ res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid))); -+ ssh_gssapi_delete_ctx(&ctx); -+ -+ return (res); -+} -+ -+/* Unprivileged */ - void - ssh_gssapi_supported_oids(gss_OID_set *oidset) - { -@@ -123,7 +158,9 @@ ssh_gssapi_supported_oids(gss_OID_set *o - gss_OID_set supported; - - gss_create_empty_oid_set(&min_status, oidset); -- gss_indicate_mechs(&min_status, &supported); -+ -+ if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported))) -+ return; - - while (supported_mechs[i]->name != NULL) { - if (GSS_ERROR(gss_test_oid_set_member(&min_status, -@@ -249,8 +286,48 @@ OM_uint32 - ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) - { - int i = 0; -+ int equal = 0; -+ gss_name_t new_name = GSS_C_NO_NAME; -+ gss_buffer_desc ename = GSS_C_EMPTY_BUFFER; -+ -+ if (options.gss_store_rekey && client->used && ctx->client_creds) { -+ if (client->mech->oid.length != ctx->oid->length || -+ (memcmp(client->mech->oid.elements, -+ ctx->oid->elements, ctx->oid->length) !=0)) { -+ debug("Rekeyed credentials have different mechanism"); -+ return GSS_S_COMPLETE; -+ } -+ -+ if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, -+ ctx->client_creds, ctx->oid, &new_name, -+ NULL, NULL, NULL))) { -+ ssh_gssapi_error(ctx); -+ return (ctx->major); -+ } - -- gss_buffer_desc ename; -+ ctx->major = gss_compare_name(&ctx->minor, client->name, -+ new_name, &equal); -+ -+ if (GSS_ERROR(ctx->major)) { -+ ssh_gssapi_error(ctx); -+ return (ctx->major); -+ } -+ -+ if (!equal) { -+ debug("Rekeyed credentials have different name"); -+ return GSS_S_COMPLETE; -+ } -+ -+ debug("Marking rekeyed credentials for export"); -+ -+ gss_release_name(&ctx->minor, &client->name); -+ gss_release_cred(&ctx->minor, &client->creds); -+ client->name = new_name; -+ client->creds = ctx->client_creds; -+ ctx->client_creds = GSS_C_NO_CREDENTIAL; -+ client->updated = 1; -+ return GSS_S_COMPLETE; -+ } - - client->mech = NULL; - -@@ -265,6 +342,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g - if (client->mech == NULL) - return GSS_S_FAILURE; - -+ if (ctx->client_creds && -+ (ctx->major = gss_inquire_cred_by_mech(&ctx->minor, -+ ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) { -+ ssh_gssapi_error(ctx); -+ return (ctx->major); -+ } -+ - if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, - &client->displayname, NULL))) { - ssh_gssapi_error(ctx); -@@ -282,6 +366,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g - return (ctx->major); - } - -+ gss_release_buffer(&ctx->minor, &ename); -+ - /* We can't copy this structure, so we just move the pointer to it */ - client->creds = ctx->client_creds; - ctx->client_creds = GSS_C_NO_CREDENTIAL; -@@ -292,11 +378,33 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g - void - ssh_gssapi_cleanup_creds(void) - { -+ struct stat krb5_ccname_stat; -+ char krb5_ccname[128], *krb5_ccname_dir_end; -+ - if (gssapi_client.store.filename != NULL) { - /* Unlink probably isn't sufficient */ - debug("removing gssapi cred file\"%s\"", - gssapi_client.store.filename); - unlink(gssapi_client.store.filename); -+ -+ /* Ticket cache: DIR::/tmp/krb5cc_876600005_T9eDKSQvzb/tkt */ -+ /* same code as in auth-krb5.c:krb5_cleanup_proc */ -+ strncpy(krb5_ccname, gssapi_client.store.filename, sizeof(krb5_ccname) - 10); -+ krb5_ccname_dir_end = strrchr(krb5_ccname, '/'); -+ if (krb5_ccname_dir_end != NULL) -+ strcpy(krb5_ccname_dir_end, "/primary"); -+ -+ if (stat(krb5_ccname, &krb5_ccname_stat) == 0) { -+ if (unlink(krb5_ccname) == 0) { -+ *krb5_ccname_dir_end = '\0'; -+ if (rmdir(krb5_ccname) == -1) -+ debug("cache dir '%s' remove failed: %s", krb5_ccname, strerror(errno)); -+ } -+ else -+ debug("cache primary file '%s', remove failed: %s", -+ krb5_ccname, strerror(errno) -+ ); -+ } - } - } - -@@ -329,7 +437,7 @@ ssh_gssapi_do_child(char ***envp, u_int - - /* Privileged */ - int --ssh_gssapi_userok(char *user) -+ssh_gssapi_userok(char *user, struct passwd *pw) - { - OM_uint32 lmin; - -@@ -339,9 +447,11 @@ ssh_gssapi_userok(char *user) - return 0; - } - if (gssapi_client.mech && gssapi_client.mech->userok) -- if ((*gssapi_client.mech->userok)(&gssapi_client, user)) -+ if ((*gssapi_client.mech->userok)(&gssapi_client, user)) { -+ gssapi_client.used = 1; -+ gssapi_client.store.owner = pw; - return 1; -- else { -+ } else { - /* Destroy delegated credentials if userok fails */ - gss_release_buffer(&lmin, &gssapi_client.displayname); - gss_release_buffer(&lmin, &gssapi_client.exportedname); -@@ -354,14 +464,90 @@ ssh_gssapi_userok(char *user) - return (0); - } - --/* Privileged */ --OM_uint32 --ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) -+/* These bits are only used for rekeying. The unpriviledged child is running -+ * as the user, the monitor is root. -+ * -+ * In the child, we want to : -+ * *) Ask the monitor to store our credentials into the store we specify -+ * *) If it succeeds, maybe do a PAM update -+ */ -+ -+/* Stuff for PAM */ -+ -+#ifdef USE_PAM -+static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, -+ struct pam_response **resp, void *data) - { -- ctx->major = gss_verify_mic(&ctx->minor, ctx->context, -- gssbuf, gssmic, NULL); -+ return (PAM_CONV_ERR); -+} -+#endif - -- return (ctx->major); -+void -+ssh_gssapi_rekey_creds() { -+ int ok; -+ int ret; -+#ifdef USE_PAM -+ pam_handle_t *pamh = NULL; -+ struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL}; -+ char *envstr; -+#endif -+ -+ if (gssapi_client.store.filename == NULL && -+ gssapi_client.store.envval == NULL && -+ gssapi_client.store.envvar == NULL) -+ return; -+ -+ ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store)); -+ -+ if (!ok) -+ return; -+ -+ debug("Rekeyed credentials stored successfully"); -+ -+ /* Actually managing to play with the ssh pam stack from here will -+ * be next to impossible. In any case, we may want different options -+ * for rekeying. So, use our own :) -+ */ -+#ifdef USE_PAM -+ if (!use_privsep) { -+ debug("Not even going to try and do PAM with privsep disabled"); -+ return; -+ } -+ -+ ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name, -+ &pamconv, &pamh); -+ if (ret) -+ return; -+ -+ xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, -+ gssapi_client.store.envval); -+ -+ ret = pam_putenv(pamh, envstr); -+ if (!ret) -+ pam_setcred(pamh, PAM_REINITIALIZE_CRED); -+ pam_end(pamh, PAM_SUCCESS); -+#endif -+} -+ -+int -+ssh_gssapi_update_creds(ssh_gssapi_ccache *store) { -+ int ok = 0; -+ -+ /* Check we've got credentials to store */ -+ if (!gssapi_client.updated) -+ return 0; -+ -+ gssapi_client.updated = 0; -+ -+ temporarily_use_uid(gssapi_client.store.owner); -+ if (gssapi_client.mech && gssapi_client.mech->updatecreds) -+ ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client); -+ else -+ debug("No update function for this mechanism"); -+ -+ restore_uid(); -+ -+ return ok; - } - - #endif -diff -up openssh-6.0p1/gss-serv-krb5.c.gsskex openssh-6.0p1/gss-serv-krb5.c ---- openssh-6.0p1/gss-serv-krb5.c.gsskex 2012-09-12 15:32:19.115689059 +0200 -+++ openssh-6.0p1/gss-serv-krb5.c 2012-09-12 16:36:15.768054426 +0200 -@@ -1,7 +1,7 @@ - /* $OpenBSD: gss-serv-krb5.c,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */ - - /* -- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions -@@ -120,6 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl - krb5_principal princ; - OM_uint32 maj_status, min_status; - int len; -+ const char *new_ccname; - - if (client->creds == NULL) { - debug("No credentials stored"); -@@ -168,11 +169,18 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl - return; - } - -- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); -+ new_ccname = krb5_cc_get_name(krb_context, ccache); -+ - client->store.envvar = "KRB5CCNAME"; -- len = strlen(client->store.filename) + 6; -- client->store.envval = xmalloc(len); -- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); -+#ifdef USE_CCAPI -+ xasprintf(&client->store.envval, "API:%s", new_ccname); -+ client->store.filename = NULL; -+#else -+ xasprintf(&client->store.envval, "DIR:%s", new_ccname); -+ if (new_ccname[0] == ':') -+ new_ccname++; -+ client->store.filename = xstrdup(new_ccname); -+#endif - - #ifdef USE_PAM - if (options.use_pam) -@@ -184,6 +192,71 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl - return; - } - -+int -+ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, -+ ssh_gssapi_client *client) -+{ -+ krb5_ccache ccache = NULL; -+ krb5_principal principal = NULL; -+ char *name = NULL; -+ krb5_error_code problem; -+ OM_uint32 maj_status, min_status; -+ -+ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { -+ logit("krb5_cc_resolve(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ return 0; -+ } -+ -+ /* Find out who the principal in this cache is */ -+ if ((problem = krb5_cc_get_principal(krb_context, ccache, -+ &principal))) { -+ logit("krb5_cc_get_principal(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ if ((problem = krb5_unparse_name(krb_context, principal, &name))) { -+ logit("krb5_unparse_name(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ -+ if (strcmp(name,client->exportedname.value)!=0) { -+ debug("Name in local credentials cache differs. Not storing"); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ krb5_free_unparsed_name(krb_context, name); -+ return 0; -+ } -+ krb5_free_unparsed_name(krb_context, name); -+ -+ /* Name matches, so lets get on with it! */ -+ -+ if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { -+ logit("krb5_cc_initialize(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ krb5_free_principal(krb_context, principal); -+ -+ if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, -+ ccache))) { -+ logit("gss_krb5_copy_ccache() failed. Sorry!"); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ return 1; -+} -+ - ssh_gssapi_mech gssapi_kerberos_mech = { - "toWM5Slw5Ew8Mqkay+al2g==", - "Kerberos", -@@ -191,7 +264,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { - NULL, - &ssh_gssapi_krb5_userok, - NULL, -- &ssh_gssapi_krb5_storecreds -+ &ssh_gssapi_krb5_storecreds, -+ &ssh_gssapi_krb5_updatecreds - }; - - #endif /* KRB5 */ -diff -up openssh-6.0p1/kex.c.gsskex openssh-6.0p1/kex.c ---- openssh-6.0p1/kex.c.gsskex 2012-09-12 15:32:19.096689136 +0200 -+++ openssh-6.0p1/kex.c 2012-09-12 15:32:28.315651579 +0200 -@@ -51,6 +51,10 @@ - #include "roaming.h" - #include "audit.h" - -+#ifdef GSSAPI -+#include "ssh-gss.h" -+#endif -+ - #if OPENSSL_VERSION_NUMBER >= 0x00907000L - # if defined(HAVE_EVP_SHA256) - # define evp_ssh_sha256 EVP_sha256 -@@ -371,6 +375,20 @@ choose_kex(Kex *k, char *client, char *s - k->kex_type = KEX_ECDH_SHA2; - k->evp_md = kex_ecdh_name_to_evpmd(k->name); - #endif -+#ifdef GSSAPI -+ } else if (strncmp(k->name, KEX_GSS_GEX_SHA1_ID, -+ sizeof(KEX_GSS_GEX_SHA1_ID) - 1) == 0) { -+ k->kex_type = KEX_GSS_GEX_SHA1; -+ k->evp_md = EVP_sha1(); -+ } else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID, -+ sizeof(KEX_GSS_GRP1_SHA1_ID) - 1) == 0) { -+ k->kex_type = KEX_GSS_GRP1_SHA1; -+ k->evp_md = EVP_sha1(); -+ } else if (strncmp(k->name, KEX_GSS_GRP14_SHA1_ID, -+ sizeof(KEX_GSS_GRP14_SHA1_ID) - 1) == 0) { -+ k->kex_type = KEX_GSS_GRP14_SHA1; -+ k->evp_md = EVP_sha1(); -+#endif - } else - fatal("bad kex alg %s", k->name); - } -diff -up openssh-6.0p1/kexgssc.c.gsskex openssh-6.0p1/kexgssc.c ---- openssh-6.0p1/kexgssc.c.gsskex 2012-09-12 15:32:19.105689098 +0200 -+++ openssh-6.0p1/kexgssc.c 2012-09-12 15:32:28.315651579 +0200 -@@ -0,0 +1,334 @@ -+/* -+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR -+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include "includes.h" -+ -+#ifdef GSSAPI -+ -+#include "includes.h" -+ -+#include -+#include -+ -+#include -+ -+#include "xmalloc.h" -+#include "buffer.h" -+#include "ssh2.h" -+#include "key.h" -+#include "cipher.h" -+#include "kex.h" -+#include "log.h" -+#include "packet.h" -+#include "dh.h" -+ -+#include "ssh-gss.h" -+ -+void -+kexgss_client(Kex *kex) { -+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; -+ gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr; -+ Gssctxt *ctxt; -+ OM_uint32 maj_status, min_status, ret_flags; -+ u_int klen, kout, slen = 0, hashlen, strlen; -+ DH *dh; -+ BIGNUM *dh_server_pub = NULL; -+ BIGNUM *shared_secret = NULL; -+ BIGNUM *p = NULL; -+ BIGNUM *g = NULL; -+ u_char *kbuf, *hash; -+ u_char *serverhostkey = NULL; -+ u_char *empty = ""; -+ char *msg; -+ char *lang; -+ int type = 0; -+ int first = 1; -+ int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX; -+ -+ /* Initialise our GSSAPI world */ -+ ssh_gssapi_build_ctx(&ctxt); -+ if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) -+ == GSS_C_NO_OID) -+ fatal("Couldn't identify host exchange"); -+ -+ if (ssh_gssapi_import_name(ctxt, kex->gss_host)) -+ fatal("Couldn't import hostname"); -+ -+ if (kex->gss_client && -+ ssh_gssapi_client_identity(ctxt, kex->gss_client)) -+ fatal("Couldn't acquire client credentials"); -+ -+ switch (kex->kex_type) { -+ case KEX_GSS_GRP1_SHA1: -+ dh = dh_new_group1(); -+ break; -+ case KEX_GSS_GRP14_SHA1: -+ dh = dh_new_group14(); -+ break; -+ case KEX_GSS_GEX_SHA1: -+ debug("Doing group exchange\n"); -+ nbits = dh_estimate(kex->we_need * 8); -+ packet_start(SSH2_MSG_KEXGSS_GROUPREQ); -+ packet_put_int(min); -+ packet_put_int(nbits); -+ packet_put_int(max); -+ -+ packet_send(); -+ -+ packet_read_expect(SSH2_MSG_KEXGSS_GROUP); -+ -+ if ((p = BN_new()) == NULL) -+ fatal("BN_new() failed"); -+ packet_get_bignum2(p); -+ if ((g = BN_new()) == NULL) -+ fatal("BN_new() failed"); -+ packet_get_bignum2(g); -+ packet_check_eom(); -+ -+ if (BN_num_bits(p) < min || BN_num_bits(p) > max) -+ fatal("GSSGRP_GEX group out of range: %d !< %d !< %d", -+ min, BN_num_bits(p), max); -+ -+ dh = dh_new_group(g, p); -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); -+ } -+ -+ /* Step 1 - e is dh->pub_key */ -+ dh_gen_key(dh, kex->we_need * 8); -+ -+ /* This is f, we initialise it now to make life easier */ -+ dh_server_pub = BN_new(); -+ if (dh_server_pub == NULL) -+ fatal("dh_server_pub == NULL"); -+ -+ token_ptr = GSS_C_NO_BUFFER; -+ -+ do { -+ debug("Calling gss_init_sec_context"); -+ -+ maj_status = ssh_gssapi_init_ctx(ctxt, -+ kex->gss_deleg_creds, token_ptr, &send_tok, -+ &ret_flags); -+ -+ if (GSS_ERROR(maj_status)) { -+ if (send_tok.length != 0) { -+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); -+ packet_put_string(send_tok.value, -+ send_tok.length); -+ } -+ fatal("gss_init_context failed"); -+ } -+ -+ /* If we've got an old receive buffer get rid of it */ -+ if (token_ptr != GSS_C_NO_BUFFER) -+ xfree(recv_tok.value); -+ -+ if (maj_status == GSS_S_COMPLETE) { -+ /* If mutual state flag is not true, kex fails */ -+ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) -+ fatal("Mutual authentication failed"); -+ -+ /* If integ avail flag is not true kex fails */ -+ if (!(ret_flags & GSS_C_INTEG_FLAG)) -+ fatal("Integrity check failed"); -+ } -+ -+ /* -+ * If we have data to send, then the last message that we -+ * received cannot have been a 'complete'. -+ */ -+ if (send_tok.length != 0) { -+ if (first) { -+ packet_start(SSH2_MSG_KEXGSS_INIT); -+ packet_put_string(send_tok.value, -+ send_tok.length); -+ packet_put_bignum2(dh->pub_key); -+ first = 0; -+ } else { -+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); -+ packet_put_string(send_tok.value, -+ send_tok.length); -+ } -+ packet_send(); -+ gss_release_buffer(&min_status, &send_tok); -+ -+ /* If we've sent them data, they should reply */ -+ do { -+ type = packet_read(); -+ if (type == SSH2_MSG_KEXGSS_HOSTKEY) { -+ debug("Received KEXGSS_HOSTKEY"); -+ if (serverhostkey) -+ fatal("Server host key received more than once"); -+ serverhostkey = -+ packet_get_string(&slen); -+ } -+ } while (type == SSH2_MSG_KEXGSS_HOSTKEY); -+ -+ switch (type) { -+ case SSH2_MSG_KEXGSS_CONTINUE: -+ debug("Received GSSAPI_CONTINUE"); -+ if (maj_status == GSS_S_COMPLETE) -+ fatal("GSSAPI Continue received from server when complete"); -+ recv_tok.value = packet_get_string(&strlen); -+ recv_tok.length = strlen; -+ break; -+ case SSH2_MSG_KEXGSS_COMPLETE: -+ debug("Received GSSAPI_COMPLETE"); -+ packet_get_bignum2(dh_server_pub); -+ msg_tok.value = packet_get_string(&strlen); -+ msg_tok.length = strlen; -+ -+ /* Is there a token included? */ -+ if (packet_get_char()) { -+ recv_tok.value= -+ packet_get_string(&strlen); -+ recv_tok.length = strlen; -+ /* If we're already complete - protocol error */ -+ if (maj_status == GSS_S_COMPLETE) -+ packet_disconnect("Protocol error: received token when complete"); -+ } else { -+ /* No token included */ -+ if (maj_status != GSS_S_COMPLETE) -+ packet_disconnect("Protocol error: did not receive final token"); -+ } -+ break; -+ case SSH2_MSG_KEXGSS_ERROR: -+ debug("Received Error"); -+ maj_status = packet_get_int(); -+ min_status = packet_get_int(); -+ msg = packet_get_string(NULL); -+ lang = packet_get_string(NULL); -+ fatal("GSSAPI Error: \n%.400s",msg); -+ default: -+ packet_disconnect("Protocol error: didn't expect packet type %d", -+ type); -+ } -+ token_ptr = &recv_tok; -+ } else { -+ /* No data, and not complete */ -+ if (maj_status != GSS_S_COMPLETE) -+ fatal("Not complete, and no token output"); -+ } -+ } while (maj_status & GSS_S_CONTINUE_NEEDED); -+ -+ /* -+ * We _must_ have received a COMPLETE message in reply from the -+ * server, which will have set dh_server_pub and msg_tok -+ */ -+ -+ if (type != SSH2_MSG_KEXGSS_COMPLETE) -+ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); -+ -+ /* Check f in range [1, p-1] */ -+ if (!dh_pub_is_valid(dh, dh_server_pub)) -+ packet_disconnect("bad server public DH value"); -+ -+ /* compute K=f^x mod p */ -+ klen = DH_size(dh); -+ kbuf = xmalloc(klen); -+ kout = DH_compute_key(kbuf, dh_server_pub, dh); -+ if ((int)kout < 0) -+ fatal("DH_compute_key: failed"); -+ -+ shared_secret = BN_new(); -+ if (shared_secret == NULL) -+ fatal("kexgss_client: BN_new failed"); -+ -+ if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) -+ fatal("kexdh_client: BN_bin2bn failed"); -+ -+ memset(kbuf, 0, klen); -+ xfree(kbuf); -+ -+ switch (kex->kex_type) { -+ case KEX_GSS_GRP1_SHA1: -+ case KEX_GSS_GRP14_SHA1: -+ kex_dh_hash( kex->client_version_string, -+ kex->server_version_string, -+ buffer_ptr(&kex->my), buffer_len(&kex->my), -+ buffer_ptr(&kex->peer), buffer_len(&kex->peer), -+ (serverhostkey ? serverhostkey : empty), slen, -+ dh->pub_key, /* e */ -+ dh_server_pub, /* f */ -+ shared_secret, /* K */ -+ &hash, &hashlen -+ ); -+ break; -+ case KEX_GSS_GEX_SHA1: -+ kexgex_hash( -+ kex->evp_md, -+ kex->client_version_string, -+ kex->server_version_string, -+ buffer_ptr(&kex->my), buffer_len(&kex->my), -+ buffer_ptr(&kex->peer), buffer_len(&kex->peer), -+ (serverhostkey ? serverhostkey : empty), slen, -+ min, nbits, max, -+ dh->p, dh->g, -+ dh->pub_key, -+ dh_server_pub, -+ shared_secret, -+ &hash, &hashlen -+ ); -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); -+ } -+ -+ gssbuf.value = hash; -+ gssbuf.length = hashlen; -+ -+ /* Verify that the hash matches the MIC we just got. */ -+ if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) -+ packet_disconnect("Hash's MIC didn't verify"); -+ -+ xfree(msg_tok.value); -+ -+ DH_free(dh); -+ if (serverhostkey) -+ xfree(serverhostkey); -+ BN_clear_free(dh_server_pub); -+ -+ /* save session id */ -+ if (kex->session_id == NULL) { -+ kex->session_id_len = hashlen; -+ kex->session_id = xmalloc(kex->session_id_len); -+ memcpy(kex->session_id, hash, kex->session_id_len); -+ } -+ -+ if (kex->gss_deleg_creds) -+ ssh_gssapi_credentials_updated(ctxt); -+ -+ if (gss_kex_context == NULL) -+ gss_kex_context = ctxt; -+ else -+ ssh_gssapi_delete_ctx(&ctxt); -+ -+ kex_derive_keys(kex, hash, hashlen, shared_secret); -+ BN_clear_free(shared_secret); -+ kex_finish(kex); -+} -+ -+#endif /* GSSAPI */ -diff -up openssh-6.0p1/kexgsss.c.gsskex openssh-6.0p1/kexgsss.c ---- openssh-6.0p1/kexgsss.c.gsskex 2012-09-12 15:32:19.116689055 +0200 -+++ openssh-6.0p1/kexgsss.c 2012-09-12 15:32:28.316651574 +0200 -@@ -0,0 +1,288 @@ -+/* -+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR -+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include "includes.h" -+ -+#ifdef GSSAPI -+ -+#include -+ -+#include -+#include -+ -+#include "xmalloc.h" -+#include "buffer.h" -+#include "ssh2.h" -+#include "key.h" -+#include "cipher.h" -+#include "kex.h" -+#include "log.h" -+#include "packet.h" -+#include "dh.h" -+#include "ssh-gss.h" -+#include "monitor_wrap.h" -+#include "servconf.h" -+ -+extern ServerOptions options; -+ -+void -+kexgss_server(Kex *kex) -+{ -+ OM_uint32 maj_status, min_status; -+ -+ /* -+ * Some GSSAPI implementations use the input value of ret_flags (an -+ * output variable) as a means of triggering mechanism specific -+ * features. Initializing it to zero avoids inadvertently -+ * activating this non-standard behaviour. -+ */ -+ -+ OM_uint32 ret_flags = 0; -+ gss_buffer_desc gssbuf, recv_tok, msg_tok; -+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; -+ Gssctxt *ctxt = NULL; -+ u_int slen, klen, kout, hashlen; -+ u_char *kbuf, *hash; -+ DH *dh; -+ int min = -1, max = -1, nbits = -1; -+ BIGNUM *shared_secret = NULL; -+ BIGNUM *dh_client_pub = NULL; -+ int type = 0; -+ gss_OID oid; -+ char *mechs; -+ -+ /* Initialise GSSAPI */ -+ -+ /* If we're rekeying, privsep means that some of the private structures -+ * in the GSSAPI code are no longer available. This kludges them back -+ * into life -+ */ -+ if (!ssh_gssapi_oid_table_ok()) -+ if ((mechs = ssh_gssapi_server_mechanisms())) -+ xfree(mechs); -+ -+ debug2("%s: Identifying %s", __func__, kex->name); -+ oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); -+ if (oid == GSS_C_NO_OID) -+ fatal("Unknown gssapi mechanism"); -+ -+ debug2("%s: Acquiring credentials", __func__); -+ -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) -+ fatal("Unable to acquire credentials for the server"); -+ -+ switch (kex->kex_type) { -+ case KEX_GSS_GRP1_SHA1: -+ dh = dh_new_group1(); -+ break; -+ case KEX_GSS_GRP14_SHA1: -+ dh = dh_new_group14(); -+ break; -+ case KEX_GSS_GEX_SHA1: -+ debug("Doing group exchange"); -+ packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ); -+ min = packet_get_int(); -+ nbits = packet_get_int(); -+ max = packet_get_int(); -+ min = MAX(DH_GRP_MIN, min); -+ max = MIN(DH_GRP_MAX, max); -+ packet_check_eom(); -+ if (max < min || nbits < min || max < nbits) -+ fatal("GSS_GEX, bad parameters: %d !< %d !< %d", -+ min, nbits, max); -+ dh = PRIVSEP(choose_dh(min, nbits, max)); -+ if (dh == NULL) -+ packet_disconnect("Protocol error: no matching group found"); -+ -+ packet_start(SSH2_MSG_KEXGSS_GROUP); -+ packet_put_bignum2(dh->p); -+ packet_put_bignum2(dh->g); -+ packet_send(); -+ -+ packet_write_wait(); -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); -+ } -+ -+ dh_gen_key(dh, kex->we_need * 8); -+ -+ do { -+ debug("Wait SSH2_MSG_GSSAPI_INIT"); -+ type = packet_read(); -+ switch(type) { -+ case SSH2_MSG_KEXGSS_INIT: -+ if (dh_client_pub != NULL) -+ fatal("Received KEXGSS_INIT after initialising"); -+ recv_tok.value = packet_get_string(&slen); -+ recv_tok.length = slen; -+ -+ if ((dh_client_pub = BN_new()) == NULL) -+ fatal("dh_client_pub == NULL"); -+ -+ packet_get_bignum2(dh_client_pub); -+ -+ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ -+ break; -+ case SSH2_MSG_KEXGSS_CONTINUE: -+ recv_tok.value = packet_get_string(&slen); -+ recv_tok.length = slen; -+ break; -+ default: -+ packet_disconnect( -+ "Protocol error: didn't expect packet type %d", -+ type); -+ } -+ -+ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, -+ &send_tok, &ret_flags)); -+ -+ xfree(recv_tok.value); -+ -+ if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) -+ fatal("Zero length token output when incomplete"); -+ -+ if (dh_client_pub == NULL) -+ fatal("No client public key"); -+ -+ if (maj_status & GSS_S_CONTINUE_NEEDED) { -+ debug("Sending GSSAPI_CONTINUE"); -+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); -+ packet_put_string(send_tok.value, send_tok.length); -+ packet_send(); -+ gss_release_buffer(&min_status, &send_tok); -+ } -+ } while (maj_status & GSS_S_CONTINUE_NEEDED); -+ -+ if (GSS_ERROR(maj_status)) { -+ if (send_tok.length > 0) { -+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); -+ packet_put_string(send_tok.value, send_tok.length); -+ packet_send(); -+ } -+ fatal("accept_ctx died"); -+ } -+ -+ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) -+ fatal("Mutual Authentication flag wasn't set"); -+ -+ if (!(ret_flags & GSS_C_INTEG_FLAG)) -+ fatal("Integrity flag wasn't set"); -+ -+ if (!dh_pub_is_valid(dh, dh_client_pub)) -+ packet_disconnect("bad client public DH value"); -+ -+ klen = DH_size(dh); -+ kbuf = xmalloc(klen); -+ kout = DH_compute_key(kbuf, dh_client_pub, dh); -+ if ((int)kout < 0) -+ fatal("DH_compute_key: failed"); -+ -+ shared_secret = BN_new(); -+ if (shared_secret == NULL) -+ fatal("kexgss_server: BN_new failed"); -+ -+ if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) -+ fatal("kexgss_server: BN_bin2bn failed"); -+ -+ memset(kbuf, 0, klen); -+ xfree(kbuf); -+ -+ switch (kex->kex_type) { -+ case KEX_GSS_GRP1_SHA1: -+ case KEX_GSS_GRP14_SHA1: -+ kex_dh_hash( -+ kex->client_version_string, kex->server_version_string, -+ buffer_ptr(&kex->peer), buffer_len(&kex->peer), -+ buffer_ptr(&kex->my), buffer_len(&kex->my), -+ NULL, 0, /* Change this if we start sending host keys */ -+ dh_client_pub, dh->pub_key, shared_secret, -+ &hash, &hashlen -+ ); -+ break; -+ case KEX_GSS_GEX_SHA1: -+ kexgex_hash( -+ kex->evp_md, -+ kex->client_version_string, kex->server_version_string, -+ buffer_ptr(&kex->peer), buffer_len(&kex->peer), -+ buffer_ptr(&kex->my), buffer_len(&kex->my), -+ NULL, 0, -+ min, nbits, max, -+ dh->p, dh->g, -+ dh_client_pub, -+ dh->pub_key, -+ shared_secret, -+ &hash, &hashlen -+ ); -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); -+ } -+ -+ BN_clear_free(dh_client_pub); -+ -+ if (kex->session_id == NULL) { -+ kex->session_id_len = hashlen; -+ kex->session_id = xmalloc(kex->session_id_len); -+ memcpy(kex->session_id, hash, kex->session_id_len); -+ } -+ -+ gssbuf.value = hash; -+ gssbuf.length = hashlen; -+ -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok)))) -+ fatal("Couldn't get MIC"); -+ -+ packet_start(SSH2_MSG_KEXGSS_COMPLETE); -+ packet_put_bignum2(dh->pub_key); -+ packet_put_string(msg_tok.value,msg_tok.length); -+ -+ if (send_tok.length != 0) { -+ packet_put_char(1); /* true */ -+ packet_put_string(send_tok.value, send_tok.length); -+ } else { -+ packet_put_char(0); /* false */ -+ } -+ packet_send(); -+ -+ gss_release_buffer(&min_status, &send_tok); -+ gss_release_buffer(&min_status, &msg_tok); -+ -+ if (gss_kex_context == NULL) -+ gss_kex_context = ctxt; -+ else -+ ssh_gssapi_delete_ctx(&ctxt); -+ -+ DH_free(dh); -+ -+ kex_derive_keys(kex, hash, hashlen, shared_secret); -+ BN_clear_free(shared_secret); -+ kex_finish(kex); -+ -+ /* If this was a rekey, then save out any delegated credentials we -+ * just exchanged. */ -+ if (options.gss_store_rekey) -+ ssh_gssapi_rekey_creds(); -+} -+#endif /* GSSAPI */ -diff -up openssh-6.0p1/kex.h.gsskex openssh-6.0p1/kex.h ---- openssh-6.0p1/kex.h.gsskex 2012-09-12 15:32:19.093689148 +0200 -+++ openssh-6.0p1/kex.h 2012-09-12 15:32:28.316651574 +0200 -@@ -73,6 +73,9 @@ enum kex_exchange { - KEX_DH_GEX_SHA1, - KEX_DH_GEX_SHA256, - KEX_ECDH_SHA2, -+ KEX_GSS_GRP1_SHA1, -+ KEX_GSS_GRP14_SHA1, -+ KEX_GSS_GEX_SHA1, - KEX_MAX - }; - -@@ -129,6 +132,12 @@ struct Kex { - sig_atomic_t done; - int flags; - const EVP_MD *evp_md; -+#ifdef GSSAPI -+ int gss_deleg_creds; -+ int gss_trust_dns; -+ char *gss_host; -+ char *gss_client; -+#endif - char *client_version_string; - char *server_version_string; - int (*verify_host_key)(Key *); -@@ -156,6 +165,11 @@ void kexgex_server(Kex *); - void kexecdh_client(Kex *); - void kexecdh_server(Kex *); - -+#ifdef GSSAPI -+void kexgss_client(Kex *); -+void kexgss_server(Kex *); -+#endif -+ - void newkeys_destroy(Newkeys *newkeys); - - void -diff -up openssh-6.0p1/key.c.gsskex openssh-6.0p1/key.c ---- openssh-6.0p1/key.c.gsskex 2012-09-12 15:32:19.103689108 +0200 -+++ openssh-6.0p1/key.c 2012-09-12 15:32:28.317651570 +0200 -@@ -1006,6 +1006,8 @@ key_ssh_name_from_type_nid(int type, int - } - break; - #endif /* OPENSSL_HAS_ECC */ -+ case KEY_NULL: -+ return "null"; - } - return "ssh-unknown"; - } -@@ -1311,6 +1313,8 @@ key_type_from_name(char *name) - strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) { - return KEY_ECDSA_CERT; - #endif -+ } else if (strcmp(name, "null") == 0) { -+ return KEY_NULL; - } - - debug2("key_type_from_name: unknown key type '%s'", name); -diff -up openssh-6.0p1/key.h.gsskex openssh-6.0p1/key.h ---- openssh-6.0p1/key.h.gsskex 2012-09-12 15:32:19.094689144 +0200 -+++ openssh-6.0p1/key.h 2012-09-12 15:32:28.318651566 +0200 -@@ -44,6 +44,7 @@ enum types { - KEY_ECDSA_CERT, - KEY_RSA_CERT_V00, - KEY_DSA_CERT_V00, -+ KEY_NULL, - KEY_UNSPEC - }; - enum fp_type { -diff -up openssh-6.0p1/Makefile.in.gsskex openssh-6.0p1/Makefile.in ---- openssh-6.0p1/Makefile.in.gsskex 2012-09-12 15:32:19.128689006 +0200 -+++ openssh-6.0p1/Makefile.in 2012-09-12 15:32:28.318651566 +0200 -@@ -75,6 +75,7 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o b - atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \ - monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ - kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ -+ kexgssc.o \ - msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o jpake.o \ - schnorr.o ssh-pkcs11.o auditstub.o - -@@ -91,7 +92,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw - auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \ - monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \ - auth-krb5.o \ -- auth2-gss.o gss-serv.o gss-serv-krb5.o \ -+ auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\ - loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \ - sftp-server.o sftp-common.o \ - roaming_common.o roaming_serv.o \ -diff -up openssh-6.0p1/monitor.c.gsskex openssh-6.0p1/monitor.c ---- openssh-6.0p1/monitor.c.gsskex 2012-09-12 15:32:19.112689072 +0200 -+++ openssh-6.0p1/monitor.c 2012-09-12 15:32:28.319651562 +0200 -@@ -186,6 +186,8 @@ int mm_answer_gss_setup_ctx(int, Buffer - int mm_answer_gss_accept_ctx(int, Buffer *); - int mm_answer_gss_userok(int, Buffer *); - int mm_answer_gss_checkmic(int, Buffer *); -+int mm_answer_gss_sign(int, Buffer *); -+int mm_answer_gss_updatecreds(int, Buffer *); - #endif - - #ifdef SSH_AUDIT_EVENTS -@@ -270,6 +272,7 @@ struct mon_table mon_dispatch_proto20[] - {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, - {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, - {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, -+ {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, - #endif - #ifdef JPAKE - {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata}, -@@ -282,6 +285,12 @@ struct mon_table mon_dispatch_proto20[] - }; - - struct mon_table mon_dispatch_postauth20[] = { -+#ifdef GSSAPI -+ {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx}, -+ {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, -+ {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, -+ {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, -+#endif - {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, - {MONITOR_REQ_SIGN, 0, mm_answer_sign}, - {MONITOR_REQ_PTY, 0, mm_answer_pty}, -@@ -406,6 +415,10 @@ monitor_child_preauth(Authctxt *_authctx - /* Permit requests for moduli and signatures */ - monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); -+#ifdef GSSAPI -+ /* and for the GSSAPI key exchange */ -+ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); -+#endif - } else { - mon_dispatch = mon_dispatch_proto15; - req_auth = &options.required_auth1; -@@ -512,6 +525,10 @@ monitor_child_postauth(struct monitor *p - monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); -+#ifdef GSSAPI -+ /* and for the GSSAPI key exchange */ -+ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); -+#endif - } else { - mon_dispatch = mon_dispatch_postauth15; - monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); -@@ -1942,6 +1959,13 @@ mm_get_kex(Buffer *m) - kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; - kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; - kex->kex[KEX_ECDH_SHA2] = kexecdh_server; -+#ifdef GSSAPI -+ if (options.gss_keyex) { -+ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; -+ } -+#endif - kex->server = 1; - kex->hostkey_type = buffer_get_int(m); - kex->kex_type = buffer_get_int(m); -@@ -2165,6 +2189,9 @@ mm_answer_gss_setup_ctx(int sock, Buffer - OM_uint32 major; - u_int len; - -+ if (!options.gss_authentication && !options.gss_keyex) -+ fatal("In GSSAPI monitor when GSSAPI is disabled"); -+ - goid.elements = buffer_get_string(m, &len); - goid.length = len; - -@@ -2192,6 +2219,9 @@ mm_answer_gss_accept_ctx(int sock, Buffe - OM_uint32 flags = 0; /* GSI needs this */ - u_int len; - -+ if (!options.gss_authentication && !options.gss_keyex) -+ fatal("In GSSAPI monitor when GSSAPI is disabled"); -+ - in.value = buffer_get_string(m, &len); - in.length = len; - major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); -@@ -2209,6 +2239,7 @@ mm_answer_gss_accept_ctx(int sock, Buffe - monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); - monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); -+ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1); - } - return (0); - } -@@ -2220,6 +2251,9 @@ mm_answer_gss_checkmic(int sock, Buffer - OM_uint32 ret; - u_int len; - -+ if (!options.gss_authentication && !options.gss_keyex) -+ fatal("In GSSAPI monitor when GSSAPI is disabled"); -+ - gssbuf.value = buffer_get_string(m, &len); - gssbuf.length = len; - mic.value = buffer_get_string(m, &len); -@@ -2246,7 +2280,11 @@ mm_answer_gss_userok(int sock, Buffer *m - { - int authenticated; - -- authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); -+ if (!options.gss_authentication && !options.gss_keyex) -+ fatal("In GSSAPI monitor when GSSAPI is disabled"); -+ -+ authenticated = authctxt->valid && -+ ssh_gssapi_userok(authctxt->user, authctxt->pw); - - buffer_clear(m); - buffer_put_int(m, authenticated); -@@ -2260,6 +2298,74 @@ mm_answer_gss_userok(int sock, Buffer *m - /* Monitor loop will terminate if authenticated */ - return (authenticated); - } -+ -+int -+mm_answer_gss_sign(int socket, Buffer *m) -+{ -+ gss_buffer_desc data; -+ gss_buffer_desc hash = GSS_C_EMPTY_BUFFER; -+ OM_uint32 major, minor; -+ u_int len; -+ -+ if (!options.gss_authentication && !options.gss_keyex) -+ fatal("In GSSAPI monitor when GSSAPI is disabled"); -+ -+ data.value = buffer_get_string(m, &len); -+ data.length = len; -+ if (data.length != 20) -+ fatal("%s: data length incorrect: %d", __func__, -+ (int) data.length); -+ -+ /* Save the session ID on the first time around */ -+ if (session_id2_len == 0) { -+ session_id2_len = data.length; -+ session_id2 = xmalloc(session_id2_len); -+ memcpy(session_id2, data.value, session_id2_len); -+ } -+ major = ssh_gssapi_sign(gsscontext, &data, &hash); -+ -+ xfree(data.value); -+ -+ buffer_clear(m); -+ buffer_put_int(m, major); -+ buffer_put_string(m, hash.value, hash.length); -+ -+ mm_request_send(socket, MONITOR_ANS_GSSSIGN, m); -+ -+ gss_release_buffer(&minor, &hash); -+ -+ /* Turn on getpwnam permissions */ -+ monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); -+ -+ /* And credential updating, for when rekeying */ -+ monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1); -+ -+ return (0); -+} -+ -+int -+mm_answer_gss_updatecreds(int socket, Buffer *m) { -+ ssh_gssapi_ccache store; -+ int ok; -+ -+ store.filename = buffer_get_string(m, NULL); -+ store.envvar = buffer_get_string(m, NULL); -+ store.envval = buffer_get_string(m, NULL); -+ -+ ok = ssh_gssapi_update_creds(&store); -+ -+ xfree(store.filename); -+ xfree(store.envvar); -+ xfree(store.envval); -+ -+ buffer_clear(m); -+ buffer_put_int(m, ok); -+ -+ mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m); -+ -+ return(0); -+} -+ - #endif /* GSSAPI */ - - #ifdef JPAKE -diff -up openssh-6.0p1/monitor.h.gsskex openssh-6.0p1/monitor.h ---- openssh-6.0p1/monitor.h.gsskex 2012-09-12 15:32:19.119689041 +0200 -+++ openssh-6.0p1/monitor.h 2012-09-12 15:32:28.319651562 +0200 -@@ -56,6 +56,8 @@ enum monitor_reqtype { - MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP, - MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK, - MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC, -+ MONITOR_REQ_GSSSIGN, MONITOR_ANS_GSSSIGN, -+ MONITOR_REQ_GSSUPCREDS, MONITOR_ANS_GSSUPCREDS, - MONITOR_REQ_PAM_START, - MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT, - MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX, -diff -up openssh-6.0p1/monitor_wrap.c.gsskex openssh-6.0p1/monitor_wrap.c ---- openssh-6.0p1/monitor_wrap.c.gsskex 2012-09-12 15:32:19.122689031 +0200 -+++ openssh-6.0p1/monitor_wrap.c 2012-09-12 15:32:28.320651557 +0200 -@@ -1326,7 +1326,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss - } - - int --mm_ssh_gssapi_userok(char *user) -+mm_ssh_gssapi_userok(char *user, struct passwd *pw) - { - Buffer m; - int authenticated = 0; -@@ -1343,6 +1343,51 @@ mm_ssh_gssapi_userok(char *user) - debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); - return (authenticated); - } -+ -+OM_uint32 -+mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) -+{ -+ Buffer m; -+ OM_uint32 major; -+ u_int len; -+ -+ buffer_init(&m); -+ buffer_put_string(&m, data->value, data->length); -+ -+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m); -+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m); -+ -+ major = buffer_get_int(&m); -+ hash->value = buffer_get_string(&m, &len); -+ hash->length = len; -+ -+ buffer_free(&m); -+ -+ return(major); -+} -+ -+int -+mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store) -+{ -+ Buffer m; -+ int ok; -+ -+ buffer_init(&m); -+ -+ buffer_put_cstring(&m, store->filename ? store->filename : ""); -+ buffer_put_cstring(&m, store->envvar ? store->envvar : ""); -+ buffer_put_cstring(&m, store->envval ? store->envval : ""); -+ -+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, &m); -+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, &m); -+ -+ ok = buffer_get_int(&m); -+ -+ buffer_free(&m); -+ -+ return (ok); -+} -+ - #endif /* GSSAPI */ - - #ifdef JPAKE -diff -up openssh-6.0p1/monitor_wrap.h.gsskex openssh-6.0p1/monitor_wrap.h ---- openssh-6.0p1/monitor_wrap.h.gsskex 2012-09-12 15:32:19.107689091 +0200 -+++ openssh-6.0p1/monitor_wrap.h 2012-09-12 15:32:28.321651552 +0200 -@@ -62,8 +62,10 @@ BIGNUM *mm_auth_rsa_generate_challenge(K - OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); - OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *, - gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); --int mm_ssh_gssapi_userok(char *user); -+int mm_ssh_gssapi_userok(char *user, struct passwd *); - OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); -+OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); -+int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *); - #endif - - #ifdef USE_PAM -diff -up openssh-6.0p1/readconf.c.gsskex openssh-6.0p1/readconf.c ---- openssh-6.0p1/readconf.c.gsskex 2012-09-12 15:32:19.100689120 +0200 -+++ openssh-6.0p1/readconf.c 2012-09-12 15:32:28.321651552 +0200 -@@ -129,6 +129,8 @@ typedef enum { - oClearAllForwardings, oNoHostAuthenticationForLocalhost, - oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, - oAddressFamily, oGssAuthentication, oGssDelegateCreds, -+ oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey, -+ oGssServerIdentity, - oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, - oSendEnv, oControlPath, oControlMaster, oControlPersist, - oHashKnownHosts, -@@ -169,10 +171,19 @@ static struct { - { "afstokenpassing", oUnsupported }, - #if defined(GSSAPI) - { "gssapiauthentication", oGssAuthentication }, -+ { "gssapikeyexchange", oGssKeyEx }, - { "gssapidelegatecredentials", oGssDelegateCreds }, -+ { "gssapitrustdns", oGssTrustDns }, -+ { "gssapiclientidentity", oGssClientIdentity }, -+ { "gssapiserveridentity", oGssServerIdentity }, -+ { "gssapirenewalforcesrekey", oGssRenewalRekey }, - #else - { "gssapiauthentication", oUnsupported }, -+ { "gssapikeyexchange", oUnsupported }, - { "gssapidelegatecredentials", oUnsupported }, -+ { "gssapitrustdns", oUnsupported }, -+ { "gssapiclientidentity", oUnsupported }, -+ { "gssapirenewalforcesrekey", oUnsupported }, - #endif - { "fallbacktorsh", oDeprecated }, - { "usersh", oDeprecated }, -@@ -483,10 +494,30 @@ parse_flag: - intptr = &options->gss_authentication; - goto parse_flag; - -+ case oGssKeyEx: -+ intptr = &options->gss_keyex; -+ goto parse_flag; -+ - case oGssDelegateCreds: - intptr = &options->gss_deleg_creds; - goto parse_flag; - -+ case oGssTrustDns: -+ intptr = &options->gss_trust_dns; -+ goto parse_flag; -+ -+ case oGssClientIdentity: -+ charptr = &options->gss_client_identity; -+ goto parse_string; -+ -+ case oGssServerIdentity: -+ charptr = &options->gss_server_identity; -+ goto parse_string; -+ -+ case oGssRenewalRekey: -+ intptr = &options->gss_renewal_rekey; -+ goto parse_flag; -+ - case oBatchMode: - intptr = &options->batch_mode; - goto parse_flag; -@@ -1139,7 +1170,12 @@ initialize_options(Options * options) - options->pubkey_authentication = -1; - options->challenge_response_authentication = -1; - options->gss_authentication = -1; -+ options->gss_keyex = -1; - options->gss_deleg_creds = -1; -+ options->gss_trust_dns = -1; -+ options->gss_renewal_rekey = -1; -+ options->gss_client_identity = NULL; -+ options->gss_server_identity = NULL; - options->password_authentication = -1; - options->kbd_interactive_authentication = -1; - options->kbd_interactive_devices = NULL; -@@ -1239,8 +1275,14 @@ fill_default_options(Options * options) - options->challenge_response_authentication = 1; - if (options->gss_authentication == -1) - options->gss_authentication = 0; -+ if (options->gss_keyex == -1) -+ options->gss_keyex = 0; - if (options->gss_deleg_creds == -1) - options->gss_deleg_creds = 0; -+ if (options->gss_trust_dns == -1) -+ options->gss_trust_dns = 0; -+ if (options->gss_renewal_rekey == -1) -+ options->gss_renewal_rekey = 0; - if (options->password_authentication == -1) - options->password_authentication = 1; - if (options->kbd_interactive_authentication == -1) -diff -up openssh-6.0p1/readconf.h.gsskex openssh-6.0p1/readconf.h ---- openssh-6.0p1/readconf.h.gsskex 2012-09-12 15:32:19.125689019 +0200 -+++ openssh-6.0p1/readconf.h 2012-09-12 15:32:28.322651548 +0200 -@@ -48,7 +48,12 @@ typedef struct { - int challenge_response_authentication; - /* Try S/Key or TIS, authentication. */ - int gss_authentication; /* Try GSS authentication */ -+ int gss_keyex; /* Try GSS key exchange */ - int gss_deleg_creds; /* Delegate GSS credentials */ -+ int gss_trust_dns; /* Trust DNS for GSS canonicalization */ -+ int gss_renewal_rekey; /* Credential renewal forces rekey */ -+ char *gss_client_identity; /* Principal to initiate GSSAPI with */ -+ char *gss_server_identity; /* GSSAPI target principal */ - int password_authentication; /* Try password - * authentication. */ - int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ -diff -up openssh-6.0p1/servconf.c.gsskex openssh-6.0p1/servconf.c ---- openssh-6.0p1/servconf.c.gsskex 2012-09-12 15:32:19.088689170 +0200 -+++ openssh-6.0p1/servconf.c 2012-09-12 15:32:28.323651545 +0200 -@@ -99,7 +99,10 @@ initialize_server_options(ServerOptions - options->kerberos_ticket_cleanup = -1; - options->kerberos_get_afs_token = -1; - options->gss_authentication=-1; -+ options->gss_keyex = -1; - options->gss_cleanup_creds = -1; -+ options->gss_strict_acceptor = -1; -+ options->gss_store_rekey = -1; - options->password_authentication = -1; - options->kbd_interactive_authentication = -1; - options->challenge_response_authentication = -1; -@@ -232,8 +235,14 @@ fill_default_server_options(ServerOption - options->kerberos_get_afs_token = 0; - if (options->gss_authentication == -1) - options->gss_authentication = 0; -+ if (options->gss_keyex == -1) -+ options->gss_keyex = 0; - if (options->gss_cleanup_creds == -1) - options->gss_cleanup_creds = 1; -+ if (options->gss_strict_acceptor == -1) -+ options->gss_strict_acceptor = 1; -+ if (options->gss_store_rekey == -1) -+ options->gss_store_rekey = 0; - if (options->password_authentication == -1) - options->password_authentication = 1; - if (options->kbd_interactive_authentication == -1) -@@ -327,7 +336,9 @@ typedef enum { - sBanner, sShowPatchLevel, sUseDNS, sHostbasedAuthentication, - sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, - sClientAliveCountMax, sAuthorizedKeysFile, -- sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, -+ sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, -+ sGssKeyEx, sGssStoreRekey, -+ sAcceptEnv, sPermitTunnel, - sRequiredAuthentications1, sRequiredAuthentications2, - sMatch, sPermitOpen, sForceCommand, sChrootDirectory, - sUsePrivilegeSeparation, sAllowAgentForwarding, -@@ -393,10 +404,20 @@ static struct { - #ifdef GSSAPI - { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, - { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, -+ { "gssapicleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL }, -+ { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, -+ { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, -+ { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, - #else - { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, - { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, -+ { "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL }, -+ { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, -+ { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, -+ { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, - #endif -+ { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL }, -+ { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL }, - { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, - { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, - { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, -@@ -983,10 +1004,22 @@ process_server_config_line(ServerOptions - intptr = &options->gss_authentication; - goto parse_flag; - -+ case sGssKeyEx: -+ intptr = &options->gss_keyex; -+ goto parse_flag; -+ - case sGssCleanupCreds: - intptr = &options->gss_cleanup_creds; - goto parse_flag; - -+ case sGssStrictAcceptor: -+ intptr = &options->gss_strict_acceptor; -+ goto parse_flag; -+ -+ case sGssStoreRekey: -+ intptr = &options->gss_store_rekey; -+ goto parse_flag; -+ - case sPasswordAuthentication: - intptr = &options->password_authentication; - goto parse_flag; -@@ -1794,6 +1827,9 @@ dump_config(ServerOptions *o) - #ifdef GSSAPI - dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); - dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); -+ dump_cfg_fmtint(sGssKeyEx, o->gss_keyex); -+ dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor); -+ dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey); - #endif - #ifdef JPAKE - dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication, -diff -up openssh-6.0p1/servconf.h.gsskex openssh-6.0p1/servconf.h ---- openssh-6.0p1/servconf.h.gsskex 2012-09-12 15:32:19.121689034 +0200 -+++ openssh-6.0p1/servconf.h 2012-09-12 15:32:28.323651545 +0200 -@@ -103,7 +103,10 @@ typedef struct { - int kerberos_get_afs_token; /* If true, try to get AFS token if - * authenticated with Kerberos. */ - int gss_authentication; /* If true, permit GSSAPI authentication */ -+ int gss_keyex; /* If true, permit GSSAPI key exchange */ - int gss_cleanup_creds; /* If true, destroy cred cache on logout */ -+ int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */ -+ int gss_store_rekey; - int password_authentication; /* If true, permit password - * authentication. */ - int kbd_interactive_authentication; /* If true, permit */ -diff -up openssh-6.0p1/ssh_config.5.gsskex openssh-6.0p1/ssh_config.5 ---- openssh-6.0p1/ssh_config.5.gsskex 2012-09-12 15:32:19.091689156 +0200 -+++ openssh-6.0p1/ssh_config.5 2012-09-12 15:32:28.324651542 +0200 -@@ -527,11 +527,43 @@ Specifies whether user authentication ba - The default is - .Dq no . - Note that this option applies to protocol version 2 only. -+.It Cm GSSAPIKeyExchange -+Specifies whether key exchange based on GSSAPI may be used. When using -+GSSAPI key exchange the server need not have a host key. -+The default is -+.Dq no . -+Note that this option applies to protocol version 2 only. -+.It Cm GSSAPIClientIdentity -+If set, specifies the GSSAPI client identity that ssh should use when -+connecting to the server. The default is unset, which means that the default -+identity will be used. -+.It Cm GSSAPIServerIdentity -+If set, specifies the GSSAPI server identity that ssh should expect when -+connecting to the server. The default is unset, which means that the -+expected GSSAPI server identity will be determined from the target -+hostname. - .It Cm GSSAPIDelegateCredentials - Forward (delegate) credentials to the server. - The default is - .Dq no . --Note that this option applies to protocol version 2 only. -+Note that this option applies to protocol version 2 connections using GSSAPI. -+.It Cm GSSAPIRenewalForcesRekey -+If set to -+.Dq yes -+then renewal of the client's GSSAPI credentials will force the rekeying of the -+ssh connection. With a compatible server, this can delegate the renewed -+credentials to a session on the server. -+The default is -+.Dq no . -+.It Cm GSSAPITrustDns -+Set to -+.Dq yes to indicate that the DNS is trusted to securely canonicalize -+the name of the host being connected to. If -+.Dq no, the hostname entered on the -+command line will be passed untouched to the GSSAPI library. -+The default is -+.Dq no . -+This option only applies to protocol version 2 connections using GSSAPI. - .It Cm HashKnownHosts - Indicates that - .Xr ssh 1 -diff -up openssh-6.0p1/ssh_config.gsskex openssh-6.0p1/ssh_config ---- openssh-6.0p1/ssh_config.gsskex 2012-09-12 15:32:19.087689174 +0200 -+++ openssh-6.0p1/ssh_config 2012-09-12 15:32:28.324651542 +0200 -@@ -26,6 +26,8 @@ - # HostbasedAuthentication no - # GSSAPIAuthentication no - # GSSAPIDelegateCredentials no -+# GSSAPIKeyExchange no -+# GSSAPITrustDNS no - # BatchMode no - # CheckHostIP yes - # AddressFamily any -diff -up openssh-6.0p1/sshconnect2.c.gsskex openssh-6.0p1/sshconnect2.c ---- openssh-6.0p1/sshconnect2.c.gsskex 2012-09-12 15:32:19.099689124 +0200 -+++ openssh-6.0p1/sshconnect2.c 2012-09-12 15:32:28.325651538 +0200 -@@ -162,9 +162,34 @@ ssh_kex2(char *host, struct sockaddr *ho - { - Kex *kex; - -+#ifdef GSSAPI -+ char *orig = NULL, *gss = NULL; -+ char *gss_host = NULL; -+#endif -+ - xxx_host = host; - xxx_hostaddr = hostaddr; - -+#ifdef GSSAPI -+ if (options.gss_keyex) { -+ /* Add the GSSAPI mechanisms currently supported on this -+ * client to the key exchange algorithm proposal */ -+ orig = myproposal[PROPOSAL_KEX_ALGS]; -+ -+ if (options.gss_trust_dns) -+ gss_host = (char *)get_canonical_hostname(1); -+ else -+ gss_host = host; -+ -+ gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity); -+ if (gss) { -+ debug("Offering GSSAPI proposal: %s", gss); -+ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], -+ "%s,%s", gss, orig); -+ } -+ } -+#endif -+ - if (options.ciphers == (char *)-1) { - logit("No valid ciphers for protocol version 2 given, using defaults."); - options.ciphers = NULL; -@@ -207,6 +232,17 @@ ssh_kex2(char *host, struct sockaddr *ho - if (options.kex_algorithms != NULL) - myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; - -+#ifdef GSSAPI -+ /* If we've got GSSAPI algorithms, then we also support the -+ * 'null' hostkey, as a last resort */ -+ if (options.gss_keyex && gss) { -+ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; -+ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], -+ "%s,null", orig); -+ xfree(gss); -+ } -+#endif -+ - if (options.rekey_limit) - packet_set_rekey_limit((u_int32_t)options.rekey_limit); - -@@ -217,10 +253,30 @@ ssh_kex2(char *host, struct sockaddr *ho - kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; - kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; - kex->kex[KEX_ECDH_SHA2] = kexecdh_client; -+#ifdef GSSAPI -+ if (options.gss_keyex) { -+ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; -+ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client; -+ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; -+ } -+#endif - kex->client_version_string=client_version_string; - kex->server_version_string=server_version_string; - kex->verify_host_key=&verify_host_key_callback; - -+#ifdef GSSAPI -+ if (options.gss_keyex) { -+ kex->gss_deleg_creds = options.gss_deleg_creds; -+ kex->gss_trust_dns = options.gss_trust_dns; -+ kex->gss_client = options.gss_client_identity; -+ if (options.gss_server_identity) { -+ kex->gss_host = options.gss_server_identity; -+ } else { -+ kex->gss_host = gss_host; -+ } -+ } -+#endif -+ - xxx_kex = kex; - - dispatch_run(DISPATCH_BLOCK, &kex->done, kex); -@@ -315,6 +371,7 @@ void input_gssapi_token(int type, u_int3 - void input_gssapi_hash(int type, u_int32_t, void *); - void input_gssapi_error(int, u_int32_t, void *); - void input_gssapi_errtok(int, u_int32_t, void *); -+int userauth_gsskeyex(Authctxt *authctxt); - #endif - - void userauth(Authctxt *, char *); -@@ -330,6 +387,11 @@ static char *authmethods_get(void); - - Authmethod authmethods[] = { - #ifdef GSSAPI -+ {"gssapi-keyex", -+ userauth_gsskeyex, -+ NULL, -+ &options.gss_authentication, -+ NULL}, - {"gssapi-with-mic", - userauth_gssapi, - NULL, -@@ -637,19 +699,31 @@ userauth_gssapi(Authctxt *authctxt) - static u_int mech = 0; - OM_uint32 min; - int ok = 0; -+ const char *gss_host; -+ -+ if (options.gss_server_identity) -+ gss_host = options.gss_server_identity; -+ else if (options.gss_trust_dns) -+ gss_host = get_canonical_hostname(1); -+ else -+ gss_host = authctxt->host; - - /* Try one GSSAPI method at a time, rather than sending them all at - * once. */ - - if (gss_supported == NULL) -- gss_indicate_mechs(&min, &gss_supported); -+ if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) { -+ gss_supported = NULL; -+ return 0; -+ } - - /* Check to see if the mechanism is usable before we offer it */ - while (mech < gss_supported->count && !ok) { - /* My DER encoding requires length<128 */ - if (gss_supported->elements[mech].length < 128 && - ssh_gssapi_check_mechanism(&gssctxt, -- &gss_supported->elements[mech], authctxt->host)) { -+ &gss_supported->elements[mech], gss_host, -+ options.gss_client_identity)) { - ok = 1; /* Mechanism works */ - } else { - mech++; -@@ -746,8 +820,8 @@ input_gssapi_response(int type, u_int32_ - { - Authctxt *authctxt = ctxt; - Gssctxt *gssctxt; -- int oidlen; -- char *oidv; -+ u_int oidlen; -+ u_char *oidv; - - if (authctxt == NULL) - fatal("input_gssapi_response: no authentication context"); -@@ -857,6 +931,48 @@ input_gssapi_error(int type, u_int32_t p - xfree(msg); - xfree(lang); - } -+ -+int -+userauth_gsskeyex(Authctxt *authctxt) -+{ -+ Buffer b; -+ gss_buffer_desc gssbuf; -+ gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; -+ OM_uint32 ms; -+ -+ static int attempt = 0; -+ if (attempt++ >= 1) -+ return (0); -+ -+ if (gss_kex_context == NULL) { -+ debug("No valid Key exchange context"); -+ return (0); -+ } -+ -+ ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service, -+ "gssapi-keyex"); -+ -+ gssbuf.value = buffer_ptr(&b); -+ gssbuf.length = buffer_len(&b); -+ -+ if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) { -+ buffer_free(&b); -+ return (0); -+ } -+ -+ packet_start(SSH2_MSG_USERAUTH_REQUEST); -+ packet_put_cstring(authctxt->server_user); -+ packet_put_cstring(authctxt->service); -+ packet_put_cstring(authctxt->method->name); -+ packet_put_string(mic.value, mic.length); -+ packet_send(); -+ -+ buffer_free(&b); -+ gss_release_buffer(&ms, &mic); -+ -+ return (1); -+} -+ - #endif /* GSSAPI */ - - int -diff -up openssh-6.0p1/sshd.c.gsskex openssh-6.0p1/sshd.c ---- openssh-6.0p1/sshd.c.gsskex 2012-09-12 15:32:19.130688998 +0200 -+++ openssh-6.0p1/sshd.c 2012-09-12 15:32:28.326651534 +0200 -@@ -124,6 +124,10 @@ - #include "ssh-sandbox.h" - #include "version.h" - -+#ifdef USE_SECURITY_SESSION_API -+#include -+#endif -+ - #ifdef LIBWRAP - #include - #include -@@ -1701,10 +1705,13 @@ main(int ac, char **av) - logit("Disabling protocol version 1. Could not load host key"); - options.protocol &= ~SSH_PROTO_1; - } -+#ifndef GSSAPI -+ /* The GSSAPI key exchange can run without a host key */ - if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { - logit("Disabling protocol version 2. Could not load host key"); - options.protocol &= ~SSH_PROTO_2; - } -+#endif - if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { - logit("sshd: no hostkeys available -- exiting."); - exit(1); -@@ -2037,6 +2044,60 @@ main(int ac, char **av) - /* Log the connection. */ - verbose("Connection from %.500s port %d", remote_ip, remote_port); - -+#ifdef USE_SECURITY_SESSION_API -+ /* -+ * Create a new security session for use by the new user login if -+ * the current session is the root session or we are not launched -+ * by inetd (eg: debugging mode or server mode). We do not -+ * necessarily need to create a session if we are launched from -+ * inetd because Panther xinetd will create a session for us. -+ * -+ * The only case where this logic will fail is if there is an -+ * inetd running in a non-root session which is not creating -+ * new sessions for us. Then all the users will end up in the -+ * same session (bad). -+ * -+ * When the client exits, the session will be destroyed for us -+ * automatically. -+ * -+ * We must create the session before any credentials are stored -+ * (including AFS pags, which happens a few lines below). -+ */ -+ { -+ OSStatus err = 0; -+ SecuritySessionId sid = 0; -+ SessionAttributeBits sattrs = 0; -+ -+ err = SessionGetInfo(callerSecuritySession, &sid, &sattrs); -+ if (err) -+ error("SessionGetInfo() failed with error %.8X", -+ (unsigned) err); -+ else -+ debug("Current Session ID is %.8X / Session Attributes are %.8X", -+ (unsigned) sid, (unsigned) sattrs); -+ -+ if (inetd_flag && !(sattrs & sessionIsRoot)) -+ debug("Running in inetd mode in a non-root session... " -+ "assuming inetd created the session for us."); -+ else { -+ debug("Creating new security session..."); -+ err = SessionCreate(0, sessionHasTTY | sessionIsRemote); -+ if (err) -+ error("SessionCreate() failed with error %.8X", -+ (unsigned) err); -+ -+ err = SessionGetInfo(callerSecuritySession, &sid, -+ &sattrs); -+ if (err) -+ error("SessionGetInfo() failed with error %.8X", -+ (unsigned) err); -+ else -+ debug("New Session ID is %.8X / Session Attributes are %.8X", -+ (unsigned) sid, (unsigned) sattrs); -+ } -+ } -+#endif -+ - /* - * We don't want to listen forever unless the other side - * successfully authenticates itself. So we set up an alarm which is -@@ -2435,6 +2496,48 @@ do_ssh2_kex(void) - - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types(); - -+#ifdef GSSAPI -+ { -+ char *orig; -+ char *gss = NULL; -+ char *newstr = NULL; -+ orig = myproposal[PROPOSAL_KEX_ALGS]; -+ -+ /* -+ * If we don't have a host key, then there's no point advertising -+ * the other key exchange algorithms -+ */ -+ -+ if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) -+ orig = NULL; -+ -+ if (options.gss_keyex) -+ gss = ssh_gssapi_server_mechanisms(); -+ else -+ gss = NULL; -+ -+ if (gss && orig) -+ xasprintf(&newstr, "%s,%s", gss, orig); -+ else if (gss) -+ newstr = gss; -+ else if (orig) -+ newstr = orig; -+ -+ /* -+ * If we've got GSSAPI mechanisms, then we've got the 'null' host -+ * key alg, but we can't tell people about it unless its the only -+ * host key algorithm we support -+ */ -+ if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) -+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null"; -+ -+ if (newstr) -+ myproposal[PROPOSAL_KEX_ALGS] = newstr; -+ else -+ fatal("No supported key exchange algorithms"); -+ } -+#endif -+ - /* start key exchange */ - kex = kex_setup(myproposal); - kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; -@@ -2442,6 +2545,13 @@ do_ssh2_kex(void) - kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; - kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; - kex->kex[KEX_ECDH_SHA2] = kexecdh_server; -+#ifdef GSSAPI -+ if (options.gss_keyex) { -+ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; -+ } -+#endif - kex->server = 1; - kex->client_version_string=client_version_string; - kex->server_version_string=server_version_string; -diff -up openssh-6.0p1/sshd_config.5.gsskex openssh-6.0p1/sshd_config.5 ---- openssh-6.0p1/sshd_config.5.gsskex 2012-09-12 15:32:19.109689084 +0200 -+++ openssh-6.0p1/sshd_config.5 2012-09-12 15:32:28.327651530 +0200 -@@ -437,12 +437,40 @@ Specifies whether user authentication ba - The default is - .Dq no . - Note that this option applies to protocol version 2 only. -+.It Cm GSSAPIKeyExchange -+Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange -+doesn't rely on ssh keys to verify host identity. -+The default is -+.Dq no . -+Note that this option applies to protocol version 2 only. - .It Cm GSSAPICleanupCredentials - Specifies whether to automatically destroy the user's credentials cache - on logout. - The default is - .Dq yes . - Note that this option applies to protocol version 2 only. -+.It Cm GSSAPIStrictAcceptorCheck -+Determines whether to be strict about the identity of the GSSAPI acceptor -+a client authenticates against. If -+.Dq yes -+then the client must authenticate against the -+.Pa host -+service on the current hostname. If -+.Dq no -+then the client may authenticate against any service key stored in the -+machine's default store. This facility is provided to assist with operation -+on multi homed machines. -+The default is -+.Dq yes . -+Note that this option applies only to protocol version 2 GSSAPI connections, -+and setting it to -+.Dq no -+may only work with recent Kerberos GSSAPI libraries. -+.It Cm GSSAPIStoreCredentialsOnRekey -+Controls whether the user's GSSAPI credentials should be updated following a -+successful connection rekeying. This option can be used to accepted renewed -+or updated credentials from a compatible client. The default is -+.Dq no . - .It Cm HostbasedAuthentication - Specifies whether rhosts or /etc/hosts.equiv authentication together - with successful public key client host authentication is allowed -diff -up openssh-6.0p1/sshd_config.gsskex openssh-6.0p1/sshd_config ---- openssh-6.0p1/sshd_config.gsskex 2012-09-12 15:32:19.102689112 +0200 -+++ openssh-6.0p1/sshd_config 2012-09-12 15:32:28.327651530 +0200 -@@ -83,6 +83,8 @@ ChallengeResponseAuthentication no - GSSAPIAuthentication yes - #GSSAPICleanupCredentials yes - GSSAPICleanupCredentials yes -+#GSSAPIStrictAcceptorCheck yes -+#GSSAPIKeyExchange no - - # Set this to 'yes' to enable PAM authentication, account processing, - # and session processing. If this is enabled, PAM authentication will -diff -up openssh-6.0p1/ssh-gss.h.gsskex openssh-6.0p1/ssh-gss.h ---- openssh-6.0p1/ssh-gss.h.gsskex 2012-09-12 15:32:19.090689160 +0200 -+++ openssh-6.0p1/ssh-gss.h 2012-09-12 15:32:28.328651526 +0200 -@@ -1,6 +1,6 @@ - /* $OpenBSD: ssh-gss.h,v 1.10 2007/06/12 08:20:00 djm Exp $ */ - /* -- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions -@@ -60,10 +60,22 @@ - - #define SSH_GSS_OIDTYPE 0x06 - -+#define SSH2_MSG_KEXGSS_INIT 30 -+#define SSH2_MSG_KEXGSS_CONTINUE 31 -+#define SSH2_MSG_KEXGSS_COMPLETE 32 -+#define SSH2_MSG_KEXGSS_HOSTKEY 33 -+#define SSH2_MSG_KEXGSS_ERROR 34 -+#define SSH2_MSG_KEXGSS_GROUPREQ 40 -+#define SSH2_MSG_KEXGSS_GROUP 41 -+#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" -+#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" -+#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" -+ - typedef struct { - char *filename; - char *envvar; - char *envval; -+ struct passwd *owner; - void *data; - } ssh_gssapi_ccache; - -@@ -71,8 +83,11 @@ typedef struct { - gss_buffer_desc displayname; - gss_buffer_desc exportedname; - gss_cred_id_t creds; -+ gss_name_t name; - struct ssh_gssapi_mech_struct *mech; - ssh_gssapi_ccache store; -+ int used; -+ int updated; - } ssh_gssapi_client; - - typedef struct ssh_gssapi_mech_struct { -@@ -83,6 +98,7 @@ typedef struct ssh_gssapi_mech_struct { - int (*userok) (ssh_gssapi_client *, char *); - int (*localname) (ssh_gssapi_client *, char **); - void (*storecreds) (ssh_gssapi_client *); -+ int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); - } ssh_gssapi_mech; - - typedef struct { -@@ -93,10 +109,11 @@ typedef struct { - gss_OID oid; /* client */ - gss_cred_id_t creds; /* server */ - gss_name_t client; /* server */ -- gss_cred_id_t client_creds; /* server */ -+ gss_cred_id_t client_creds; /* both */ - } Gssctxt; - - extern ssh_gssapi_mech *supported_mechs[]; -+extern Gssctxt *gss_kex_context; - - int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); - void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); -@@ -116,16 +133,30 @@ void ssh_gssapi_build_ctx(Gssctxt **); - void ssh_gssapi_delete_ctx(Gssctxt **); - OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); - void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *); --int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); -+int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); -+OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); -+int ssh_gssapi_credentials_updated(Gssctxt *); - - /* In the server */ -+typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, -+ const char *); -+char *ssh_gssapi_client_mechanisms(const char *, const char *); -+char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, -+ const char *); -+gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); -+int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, -+ const char *); - OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); --int ssh_gssapi_userok(char *name); -+int ssh_gssapi_userok(char *name, struct passwd *); - OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); - void ssh_gssapi_do_child(char ***, u_int *); - void ssh_gssapi_cleanup_creds(void); - void ssh_gssapi_storecreds(void); - -+char *ssh_gssapi_server_mechanisms(void); -+int ssh_gssapi_oid_table_ok(); -+ -+int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); - #endif /* GSSAPI */ - - #endif /* _SSH_GSS_H */ diff --git a/openssh-6.1p1-akc.patch b/openssh-6.1p1-akc.patch new file mode 100644 index 0000000..49fa169 --- /dev/null +++ b/openssh-6.1p1-akc.patch @@ -0,0 +1,452 @@ +diff -up openssh-6.1p1/auth2-pubkey.c.akc openssh-6.1p1/auth2-pubkey.c +--- openssh-6.1p1/auth2-pubkey.c.akc 2012-09-14 20:20:48.459445650 +0200 ++++ openssh-6.1p1/auth2-pubkey.c 2012-09-14 20:20:48.520446072 +0200 +@@ -27,6 +27,7 @@ + + #include + #include ++#include + + #include + #include +@@ -277,27 +278,15 @@ match_principals_file(char *file, struct + + /* return 1 if user allows given key */ + static int +-user_key_allowed2(struct passwd *pw, Key *key, char *file) ++user_search_key_in_file(FILE *f, char *file, Key* key, struct passwd *pw) + { + char line[SSH_MAX_PUBKEY_BYTES]; + const char *reason; + int found_key = 0; +- FILE *f; + u_long linenum = 0; + Key *found; + char *fp; + +- /* Temporarily use the user's uid. */ +- temporarily_use_uid(pw); +- +- debug("trying public key file %s", file); +- f = auth_openkeyfile(file, pw, options.strict_modes); +- +- if (!f) { +- restore_uid(); +- return 0; +- } +- + found_key = 0; + found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type); + +@@ -390,8 +379,6 @@ user_key_allowed2(struct passwd *pw, Key + break; + } + } +- restore_uid(); +- fclose(f); + key_free(found); + if (!found_key) + debug2("key not found"); +@@ -453,13 +440,191 @@ user_cert_trusted_ca(struct passwd *pw, + return ret; + } + +-/* check whether given key is in .ssh/authorized_keys* */ ++/* return 1 if user allows given key */ ++static int ++user_key_allowed2(struct passwd *pw, Key *key, char *file) ++{ ++ FILE *f; ++ int found_key = 0; ++ ++ /* Temporarily use the user's uid. */ ++ temporarily_use_uid(pw); ++ ++ debug("trying public key file %s", file); ++ f = auth_openkeyfile(file, pw, options.strict_modes); ++ ++ if (f) { ++ found_key = user_search_key_in_file (f, file, key, pw); ++ fclose(f); ++ } ++ ++ restore_uid(); ++ return found_key; ++} ++ ++#ifdef WITH_AUTHORIZED_KEYS_COMMAND ++ ++#define WHITESPACE " \t\r\n" ++ ++/* return 1 if user allows given key */ ++static int ++user_key_via_command_allowed2(struct passwd *pw, Key *key) ++{ ++ FILE *f; ++ int found_key = 0; ++ char *progname = NULL; ++ char *cp; ++ struct passwd *runas_pw; ++ struct stat st; ++ int childdescriptors[2], i; ++ pid_t pstat, pid, child; ++ ++ if (options.authorized_keys_command == NULL || options.authorized_keys_command[0] != '/') ++ return 0; ++ ++ /* get the run as identity from config */ ++ runas_pw = (options.authorized_keys_command_runas == NULL)? pw ++ : getpwnam (options.authorized_keys_command_runas); ++ if (!runas_pw) { ++ error("%s: getpwnam(\"%s\"): %s", __func__, ++ options.authorized_keys_command_runas, strerror(errno)); ++ return 0; ++ } ++ ++ /* Temporarily use the specified uid. */ ++ if (runas_pw->pw_uid != 0) ++ temporarily_use_uid(runas_pw); ++ ++ progname = xstrdup(options.authorized_keys_command); ++ ++ debug3("%s: checking program '%s'", __func__, progname); ++ ++ if (stat (progname, &st) < 0) { ++ error("%s: stat(\"%s\"): %s", __func__, ++ progname, strerror(errno)); ++ goto go_away; ++ } ++ ++ if (st.st_uid != 0 || (st.st_mode & 022) != 0) { ++ error("bad ownership or modes for AuthorizedKeysCommand \"%s\"", ++ progname); ++ goto go_away; ++ } ++ ++ if (!S_ISREG(st.st_mode)) { ++ error("AuthorizedKeysCommand \"%s\" is not a regular file", ++ progname); ++ goto go_away; ++ } ++ ++ /* ++ * Descend the path, checking that each component is a ++ * root-owned directory with strict permissions. ++ */ ++ do { ++ if ((cp = strrchr(progname, '/')) == NULL) ++ break; ++ else ++ *cp = '\0'; ++ ++ debug3("%s: checking component '%s'", __func__, (*progname == '\0' ? "/" : progname)); ++ ++ if (stat((*progname == '\0' ? "/" : progname), &st) != 0) { ++ error("%s: stat(\"%s\"): %s", __func__, ++ progname, strerror(errno)); ++ goto go_away; ++ } ++ if (st.st_uid != 0 || (st.st_mode & 022) != 0) { ++ error("bad ownership or modes for AuthorizedKeysCommand path component \"%s\"", ++ progname); ++ goto go_away; ++ } ++ if (!S_ISDIR(st.st_mode)) { ++ error("AuthorizedKeysCommand path component \"%s\" is not a directory", ++ progname); ++ goto go_away; ++ } ++ } while (1); ++ ++ /* open the pipe and read the keys */ ++ if (pipe(childdescriptors)) { ++ error("failed to pipe(2) for AuthorizedKeysCommand: %s", ++ strerror(errno)); ++ goto go_away; ++ } ++ ++ child = fork(); ++ if (child == -1) { ++ error("failed to fork(2) for AuthorizedKeysCommand: %s", ++ strerror(errno)); ++ goto go_away; ++ } else if (child == 0) { ++ /* we're in the child process here -- we should never return from this block. */ ++ /* permanently drop privs in child process */ ++ if (runas_pw->pw_uid != 0) { ++ restore_uid(); ++ permanently_set_uid(runas_pw); ++ } ++ ++ close(childdescriptors[0]); ++ /* put the write end of the pipe on stdout (FD 1) */ ++ if (dup2(childdescriptors[1], 1) == -1) { ++ error("failed to dup2(2) from AuthorizedKeysCommand: %s", ++ strerror(errno)); ++ _exit(127); ++ } ++ ++ debug3("about to execl() AuthorizedKeysCommand: \"%s\" \"%s\"", options.authorized_keys_command, pw->pw_name); ++ /* see session.c:child_close_fds() */ ++ for (i = 3; i < 64; ++i) { ++ close(i); ++ } ++ ++ execl(options.authorized_keys_command, options.authorized_keys_command, pw->pw_name, NULL); ++ ++ /* if we got here, it didn't work */ ++ error("failed to execl AuthorizedKeysCommand: %s", strerror(errno)); /* this won't work because we closed the fds above */ ++ _exit(127); ++ } ++ ++ close(childdescriptors[1]); ++ f = fdopen(childdescriptors[0], "r"); ++ if (!f) { ++ error("%s: could not buffer FDs from AuthorizedKeysCommand (\"%s\", \"r\"): %s", __func__, ++ options.authorized_keys_command, strerror (errno)); ++ goto go_away; ++ } ++ ++ found_key = user_search_key_in_file (f, options.authorized_keys_command, key, pw); ++ fclose (f); ++ do { ++ pid = waitpid(child, &pstat, 0); ++ } while (pid == -1 && errno == EINTR); ++ ++ /* what about the return value from the child process? */ ++go_away: ++ if (progname) ++ xfree (progname); ++ ++ if (runas_pw->pw_uid != 0) ++ restore_uid(); ++ return found_key; ++} ++#endif ++ ++/* check whether given key is in 0) ++ return success; ++#endif ++ + if (auth_key_is_revoked(key)) + return 0; + if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key)) +diff -up openssh-6.1p1/configure.ac.akc openssh-6.1p1/configure.ac +--- openssh-6.1p1/configure.ac.akc 2012-07-06 03:49:29.000000000 +0200 ++++ openssh-6.1p1/configure.ac 2012-09-14 20:20:48.525446106 +0200 +@@ -1512,6 +1512,18 @@ AC_ARG_WITH([audit], + esac ] + ) + ++# Check whether user wants AuthorizedKeysCommand support ++AKC_MSG="no" ++AC_ARG_WITH(authorized-keys-command, ++ [ --with-authorized-keys-command Enable AuthorizedKeysCommand support], ++ [ ++ if test "x$withval" != "xno" ; then ++ AC_DEFINE([WITH_AUTHORIZED_KEYS_COMMAND], 1, [Enable AuthorizedKeysCommand support]) ++ AKC_MSG="yes" ++ fi ++ ] ++) ++ + dnl Checks for library functions. Please keep in alphabetical order + AC_CHECK_FUNCS([ \ + arc4random \ +@@ -4407,6 +4419,7 @@ echo " SELinux support + echo " Smartcard support: $SCARD_MSG" + echo " S/KEY support: $SKEY_MSG" + echo " TCP Wrappers support: $TCPW_MSG" ++echo " AuthorizedKeysCommand support: $AKC_MSG" + echo " MD5 password support: $MD5_MSG" + echo " libedit support: $LIBEDIT_MSG" + echo " Solaris process contract support: $SPC_MSG" +diff -up openssh-6.1p1/servconf.c.akc openssh-6.1p1/servconf.c +--- openssh-6.1p1/servconf.c.akc 2012-09-14 20:20:48.138443423 +0200 ++++ openssh-6.1p1/servconf.c 2012-09-14 20:27:34.546107295 +0200 +@@ -139,6 +139,8 @@ initialize_server_options(ServerOptions + options->num_permitted_opens = -1; + options->adm_forced_command = NULL; + options->chroot_directory = NULL; ++ options->authorized_keys_command = NULL; ++ options->authorized_keys_command_runas = NULL; + options->zero_knowledge_password_authentication = -1; + options->revoked_keys_file = NULL; + options->trusted_user_ca_keys = NULL; +@@ -334,6 +336,7 @@ typedef enum { + sZeroKnowledgePasswordAuthentication, sHostCertificate, + sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, + sKexAlgorithms, sIPQoS, sVersionAddendum, ++ sAuthorizedKeysCommand, sAuthorizedKeysCommandRunAs, + sDeprecated, sUnsupported + } ServerOpCodes; + +@@ -461,6 +464,14 @@ static struct { + { "requiredauthentications2", sRequiredAuthentications2, SSHCFG_ALL }, + { "ipqos", sIPQoS, SSHCFG_ALL }, + { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, ++#ifdef WITH_AUTHORIZED_KEYS_COMMAND ++ { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, ++ { "authorizedkeyscommandrunas", sAuthorizedKeysCommandRunAs, SSHCFG_ALL }, ++#else ++ { "authorizedkeyscommand", sUnsupported, SSHCFG_ALL }, ++ { "authorizedkeyscommandrunas", sUnsupported, SSHCFG_ALL }, ++#endif ++ + { NULL, sBadOption, 0 } + }; + +@@ -1532,6 +1543,24 @@ process_server_config_line(ServerOptions + } + return 0; + ++ case sAuthorizedKeysCommand: ++ len = strspn(cp, WHITESPACE); ++ if (*activep && options->authorized_keys_command == NULL) ++ options->authorized_keys_command = xstrdup(cp + len); ++ return 0; ++ ++ case sAuthorizedKeysCommandRunAs: ++ charptr = &options->authorized_keys_command_runas; ++ ++ arg = strdelim(&cp); ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: missing account.", ++ filename, linenum); ++ ++ if (*activep && *charptr == NULL) ++ *charptr = xstrdup(arg); ++ break; ++ + case sDeprecated: + logit("%s line %d: Deprecated option %s", + filename, linenum, arg); +@@ -1682,6 +1711,8 @@ copy_set_server_options(ServerOptions *d + M_CP_INTOPT(hostbased_uses_name_from_packet_only); + M_CP_INTOPT(kbd_interactive_authentication); + M_CP_INTOPT(zero_knowledge_password_authentication); ++ M_CP_STROPT(authorized_keys_command); ++ M_CP_STROPT(authorized_keys_command_runas); + M_CP_INTOPT(permit_root_login); + M_CP_INTOPT(permit_empty_passwd); + +@@ -1942,6 +1973,8 @@ dump_config(ServerOptions *o) + dump_cfg_string(sAuthorizedPrincipalsFile, + o->authorized_principals_file); + dump_cfg_string(sVersionAddendum, o->version_addendum); ++ dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command); ++ dump_cfg_string(sAuthorizedKeysCommandRunAs, o->authorized_keys_command_runas); + + /* string arguments requiring a lookup */ + dump_cfg_string(sLogLevel, log_level_name(o->log_level)); +diff -up openssh-6.1p1/servconf.h.akc openssh-6.1p1/servconf.h +--- openssh-6.1p1/servconf.h.akc 2012-09-14 20:20:48.000000000 +0200 ++++ openssh-6.1p1/servconf.h 2012-09-14 20:23:16.691844577 +0200 +@@ -169,6 +169,8 @@ typedef struct { + char *revoked_keys_file; + char *trusted_user_ca_keys; + char *authorized_principals_file; ++ char *authorized_keys_command; ++ char *authorized_keys_command_runas; + + char *version_addendum; /* Appended to SSH banner */ + } ServerOptions; +diff -up openssh-6.1p1/sshd_config.akc openssh-6.1p1/sshd_config +--- openssh-6.1p1/sshd_config.akc 2012-07-31 04:21:34.000000000 +0200 ++++ openssh-6.1p1/sshd_config 2012-09-14 20:30:46.950095769 +0200 +@@ -49,6 +49,9 @@ + # but this is overridden so installations will only check .ssh/authorized_keys + AuthorizedKeysFile .ssh/authorized_keys + ++#AuthorizedKeysCommand none ++#AuthorizedKeysCommandRunAs nobody ++ + #AuthorizedPrincipalsFile none + + # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts +diff -up openssh-6.1p1/sshd_config.0.akc openssh-6.1p1/sshd_config.0 +--- openssh-6.1p1/sshd_config.0.akc 2012-08-29 02:53:04.000000000 +0200 ++++ openssh-6.1p1/sshd_config.0 2012-09-14 20:32:23.539624859 +0200 +@@ -71,6 +71,23 @@ DESCRIPTION + + See PATTERNS in ssh_config(5) for more information on patterns. + ++ AuthorizedKeysCommand ++ ++ Specifies a program to be used for lookup of the user's ++ public keys. The program will be invoked with its first ++ argument the name of the user being authorized, and should produce ++ on standard output AuthorizedKeys lines (see AUTHORIZED_KEYS ++ in sshd(8)). By default (or when set to the empty string) there is no ++ AuthorizedKeysCommand run. If the AuthorizedKeysCommand does not successfully ++ authorize the user, authorization falls through to the ++ AuthorizedKeysFile. Note that this option has an effect ++ only with PubkeyAuthentication turned on. ++ ++ AuthorizedKeysCommandRunAs ++ Specifies the user under whose account the AuthorizedKeysCommand is run. ++ Empty string (the default value) means the user being authorized ++ is used. ++ + AuthorizedKeysFile + Specifies the file that contains the public keys that can be used + for user authentication. The format is described in the +@@ -402,7 +419,8 @@ DESCRIPTION + Only a subset of keywords may be used on the lines following a + Match keyword. Available keywords are AcceptEnv, + AllowAgentForwarding, AllowGroups, AllowTcpForwarding, +- AllowUsers, AuthorizedKeysFile, AuthorizedPrincipalsFile, Banner, ++ AllowUsers, AuthorizedKeysFile, AuthorizedKeysCommand, ++ AuthorizedKeysCommandRunAs, AuthorizedPrincipalsFile, Banner, + ChrootDirectory, DenyGroups, DenyUsers, ForceCommand, + GatewayPorts, GSSAPIAuthentication, HostbasedAuthentication, + HostbasedUsesNameFromPacketOnly, KbdInteractiveAuthentication, +diff -up openssh-6.1p1/sshd_config.5.akc openssh-6.1p1/sshd_config.5 +--- openssh-6.1p1/sshd_config.5.akc 2012-09-14 20:20:48.142443448 +0200 ++++ openssh-6.1p1/sshd_config.5 2012-09-14 20:29:56.003873873 +0200 +@@ -151,6 +151,19 @@ See + in + .Xr ssh_config 5 + for more information on patterns. ++.It Cm AuthorizedKeysCommand ++Specifies a program to be used for lookup of the user's ++public keys. The program will be invoked with its first ++argument the name of the user being authorized, and should produce ++on standard output AuthorizedKeys lines (see AUTHORIZED_KEYS ++in sshd(8)). By default (or when set to the empty string) there is no ++AuthorizedKeysCommand run. If the AuthorizedKeysCommand does not successfully ++authorize the user, authorization falls through to the ++AuthorizedKeysFile. Note that this option has an effect ++only with PubkeyAuthentication turned on. ++.It Cm AuthorizedKeysCommandRunAs ++Specifies the user under whose account the AuthorizedKeysCommand is run. Empty ++string (the default value) means the user being authorized is used. + .It Cm AuthorizedKeysFile + Specifies the file that contains the public keys that can be used + for user authentication. +@@ -712,6 +725,8 @@ Available keywords are + .Cm AllowTcpForwarding , + .Cm AllowUsers , + .Cm AuthorizedKeysFile , ++.Cm AuthorizedKeysCommand , ++.Cm AuthorizedKeysCommandRunAs , + .Cm AuthorizedPrincipalsFile , + .Cm Banner , + .Cm ChrootDirectory , +@@ -726,6 +741,7 @@ Available keywords are + .Cm KerberosAuthentication , + .Cm MaxAuthTries , + .Cm MaxSessions , ++.Cm PubkeyAuthentication , + .Cm PasswordAuthentication , + .Cm PermitEmptyPasswords , + .Cm PermitOpen , diff --git a/openssh-6.1p1-askpass-ld.patch b/openssh-6.1p1-askpass-ld.patch new file mode 100644 index 0000000..f7a7fac --- /dev/null +++ b/openssh-6.1p1-askpass-ld.patch @@ -0,0 +1,18 @@ +diff -up openssh-6.1p1/contrib/Makefile.askpass-ld openssh-6.1p1/contrib/Makefile +--- openssh-6.1p1/contrib/Makefile.askpass-ld 2012-05-19 07:24:37.000000000 +0200 ++++ openssh-6.1p1/contrib/Makefile 2012-09-14 20:35:47.565704718 +0200 +@@ -4,12 +4,12 @@ all: + @echo "Valid targets: gnome-ssh-askpass1 gnome-ssh-askpass2" + + gnome-ssh-askpass1: gnome-ssh-askpass1.c +- $(CC) `gnome-config --cflags gnome gnomeui` \ ++ $(CC) ${CFLAGS} `gnome-config --cflags gnome gnomeui` \ + gnome-ssh-askpass1.c -o gnome-ssh-askpass1 \ + `gnome-config --libs gnome gnomeui` + + gnome-ssh-askpass2: gnome-ssh-askpass2.c +- $(CC) `$(PKG_CONFIG) --cflags gtk+-2.0` \ ++ $(CC) ${CFLAGS} `$(PKG_CONFIG) --cflags gtk+-2.0` \ + gnome-ssh-askpass2.c -o gnome-ssh-askpass2 \ + `$(PKG_CONFIG) --libs gtk+-2.0 x11` + diff --git a/openssh-6.1p1-coverity.patch b/openssh-6.1p1-coverity.patch new file mode 100644 index 0000000..0c8fb23 --- /dev/null +++ b/openssh-6.1p1-coverity.patch @@ -0,0 +1,806 @@ +diff -up openssh-6.1p1/auth-pam.c.coverity openssh-6.1p1/auth-pam.c +--- openssh-6.1p1/auth-pam.c.coverity 2009-07-12 14:07:21.000000000 +0200 ++++ openssh-6.1p1/auth-pam.c 2012-09-14 21:16:41.264906486 +0200 +@@ -216,7 +216,12 @@ pthread_join(sp_pthread_t thread, void * + if (sshpam_thread_status != -1) + return (sshpam_thread_status); + signal(SIGCHLD, sshpam_oldsig); +- waitpid(thread, &status, 0); ++ while (waitpid(thread, &status, 0) < 0) { ++ if (errno == EINTR) ++ continue; ++ fatal("%s: waitpid: %s", __func__, ++ strerror(errno)); ++ } + return (status); + } + #endif +diff -up openssh-6.1p1/clientloop.c.coverity openssh-6.1p1/clientloop.c +--- openssh-6.1p1/clientloop.c.coverity 2012-06-20 14:31:27.000000000 +0200 ++++ openssh-6.1p1/clientloop.c 2012-09-14 21:16:41.267906501 +0200 +@@ -2006,14 +2006,15 @@ client_input_global_request(int type, u_ + char *rtype; + int want_reply; + int success = 0; ++/* success is still 0 the packet is allways SSH2_MSG_REQUEST_FAILURE, isn't it? */ + + rtype = packet_get_string(NULL); + want_reply = packet_get_char(); + debug("client_input_global_request: rtype %s want_reply %d", + rtype, want_reply); + if (want_reply) { +- packet_start(success ? +- SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); ++ packet_start(/*success ? ++ SSH2_MSG_REQUEST_SUCCESS :*/ SSH2_MSG_REQUEST_FAILURE); + packet_send(); + packet_write_wait(); + } +diff -up openssh-6.1p1/channels.c.coverity openssh-6.1p1/channels.c +--- openssh-6.1p1/channels.c.coverity 2012-04-23 10:21:05.000000000 +0200 ++++ openssh-6.1p1/channels.c 2012-09-14 21:16:41.272906528 +0200 +@@ -232,11 +232,11 @@ channel_register_fds(Channel *c, int rfd + channel_max_fd = MAX(channel_max_fd, wfd); + channel_max_fd = MAX(channel_max_fd, efd); + +- if (rfd != -1) ++ if (rfd >= 0) + fcntl(rfd, F_SETFD, FD_CLOEXEC); +- if (wfd != -1 && wfd != rfd) ++ if (wfd >= 0 && wfd != rfd) + fcntl(wfd, F_SETFD, FD_CLOEXEC); +- if (efd != -1 && efd != rfd && efd != wfd) ++ if (efd >= 0 && efd != rfd && efd != wfd) + fcntl(efd, F_SETFD, FD_CLOEXEC); + + c->rfd = rfd; +@@ -251,11 +251,11 @@ channel_register_fds(Channel *c, int rfd + + /* enable nonblocking mode */ + if (nonblock) { +- if (rfd != -1) ++ if (rfd >= 0) + set_nonblock(rfd); +- if (wfd != -1) ++ if (wfd >= 0) + set_nonblock(wfd); +- if (efd != -1) ++ if (efd >= 0) + set_nonblock(efd); + } + } +diff -up openssh-6.1p1/key.c.coverity openssh-6.1p1/key.c +--- openssh-6.1p1/key.c.coverity 2012-06-30 12:05:02.000000000 +0200 ++++ openssh-6.1p1/key.c 2012-09-14 21:16:41.274906537 +0200 +@@ -808,8 +808,10 @@ key_read(Key *ret, char **cpp) + success = 1; + /*XXXX*/ + key_free(k); ++/*XXXX + if (success != 1) + break; ++XXXX*/ + /* advance cp: skip whitespace and data */ + while (*cp == ' ' || *cp == '\t') + cp++; +diff -up openssh-6.1p1/monitor.c.coverity openssh-6.1p1/monitor.c +--- openssh-6.1p1/monitor.c.coverity 2012-06-30 00:33:17.000000000 +0200 ++++ openssh-6.1p1/monitor.c 2012-09-14 21:16:41.277906552 +0200 +@@ -420,7 +420,7 @@ monitor_child_preauth(Authctxt *_authctx + } + + /* Drain any buffered messages from the child */ +- while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) ++ while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0) + ; + + if (!authctxt->valid) +@@ -1159,6 +1159,10 @@ mm_answer_keyallowed(int sock, Buffer *m + break; + } + } ++ ++ debug3("%s: key %p is %s", ++ __func__, key, allowed ? "allowed" : "not allowed"); ++ + if (key != NULL) + key_free(key); + +@@ -1180,9 +1184,6 @@ mm_answer_keyallowed(int sock, Buffer *m + xfree(chost); + } + +- debug3("%s: key %p is %s", +- __func__, key, allowed ? "allowed" : "not allowed"); +- + buffer_clear(m); + buffer_put_int(m, allowed); + buffer_put_int(m, forced_command != NULL); +diff -up openssh-6.1p1/monitor_wrap.c.coverity openssh-6.1p1/monitor_wrap.c +--- openssh-6.1p1/monitor_wrap.c.coverity 2011-06-20 06:42:23.000000000 +0200 ++++ openssh-6.1p1/monitor_wrap.c 2012-09-14 21:16:41.280906568 +0200 +@@ -707,10 +707,10 @@ mm_pty_allocate(int *ptyfd, int *ttyfd, + if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 || + (tmp2 = dup(pmonitor->m_recvfd)) == -1) { + error("%s: cannot allocate fds for pty", __func__); +- if (tmp1 > 0) ++ if (tmp1 >= 0) + close(tmp1); +- if (tmp2 > 0) +- close(tmp2); ++ /*DEAD CODE if (tmp2 >= 0) ++ close(tmp2);*/ + return 0; + } + close(tmp1); +diff -up openssh-6.1p1/openbsd-compat/bindresvport.c.coverity openssh-6.1p1/openbsd-compat/bindresvport.c +--- openssh-6.1p1/openbsd-compat/bindresvport.c.coverity 2010-12-03 00:50:26.000000000 +0100 ++++ openssh-6.1p1/openbsd-compat/bindresvport.c 2012-09-14 21:16:41.281906573 +0200 +@@ -58,7 +58,7 @@ bindresvport_sa(int sd, struct sockaddr + struct sockaddr_in6 *in6; + u_int16_t *portp; + u_int16_t port; +- socklen_t salen; ++ socklen_t salen = sizeof(struct sockaddr_storage); + int i; + + if (sa == NULL) { +diff -up openssh-6.1p1/packet.c.coverity openssh-6.1p1/packet.c +--- openssh-6.1p1/packet.c.coverity 2012-03-09 00:28:07.000000000 +0100 ++++ openssh-6.1p1/packet.c 2012-09-14 21:16:41.284906588 +0200 +@@ -1177,6 +1177,7 @@ packet_read_poll1(void) + case DEATTACK_DETECTED: + packet_disconnect("crc32 compensation attack: " + "network attack detected"); ++ break; + case DEATTACK_DOS_DETECTED: + packet_disconnect("deattack denial of " + "service detected"); +@@ -1678,7 +1679,7 @@ void + packet_write_wait(void) + { + fd_set *setp; +- int ret, ms_remain; ++ int ret, ms_remain = 0; + struct timeval start, timeout, *timeoutp = NULL; + + setp = (fd_set *)xcalloc(howmany(active_state->connection_out + 1, +diff -up openssh-6.1p1/progressmeter.c.coverity openssh-6.1p1/progressmeter.c +--- openssh-6.1p1/progressmeter.c.coverity 2006-08-05 04:39:40.000000000 +0200 ++++ openssh-6.1p1/progressmeter.c 2012-09-14 21:16:41.285906593 +0200 +@@ -65,7 +65,7 @@ static void update_progress_meter(int); + + static time_t start; /* start progress */ + static time_t last_update; /* last progress update */ +-static char *file; /* name of the file being transferred */ ++static const char *file; /* name of the file being transferred */ + static off_t end_pos; /* ending position of transfer */ + static off_t cur_pos; /* transfer position as of last refresh */ + static volatile off_t *counter; /* progress counter */ +@@ -247,7 +247,7 @@ update_progress_meter(int ignore) + } + + void +-start_progress_meter(char *f, off_t filesize, off_t *ctr) ++start_progress_meter(const char *f, off_t filesize, off_t *ctr) + { + start = last_update = time(NULL); + file = f; +diff -up openssh-6.1p1/progressmeter.h.coverity openssh-6.1p1/progressmeter.h +--- openssh-6.1p1/progressmeter.h.coverity 2006-03-26 05:30:02.000000000 +0200 ++++ openssh-6.1p1/progressmeter.h 2012-09-14 21:16:41.286906598 +0200 +@@ -23,5 +23,5 @@ + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +-void start_progress_meter(char *, off_t, off_t *); ++void start_progress_meter(const char *, off_t, off_t *); + void stop_progress_meter(void); +diff -up openssh-6.1p1/scp.c.coverity openssh-6.1p1/scp.c +--- openssh-6.1p1/scp.c.coverity 2011-09-22 13:38:01.000000000 +0200 ++++ openssh-6.1p1/scp.c 2012-09-14 21:16:41.288906608 +0200 +@@ -155,7 +155,7 @@ killchild(int signo) + { + if (do_cmd_pid > 1) { + kill(do_cmd_pid, signo ? signo : SIGTERM); +- waitpid(do_cmd_pid, NULL, 0); ++ (void) waitpid(do_cmd_pid, NULL, 0); + } + + if (signo) +diff -up openssh-6.1p1/servconf.c.coverity openssh-6.1p1/servconf.c +--- openssh-6.1p1/servconf.c.coverity 2012-07-31 04:22:38.000000000 +0200 ++++ openssh-6.1p1/servconf.c 2012-09-14 21:16:41.291906623 +0200 +@@ -1249,7 +1249,7 @@ process_server_config_line(ServerOptions + fatal("%s line %d: Missing subsystem name.", + filename, linenum); + if (!*activep) { +- arg = strdelim(&cp); ++ /*arg =*/ (void) strdelim(&cp); + break; + } + for (i = 0; i < options->num_subsystems; i++) +@@ -1340,8 +1340,9 @@ process_server_config_line(ServerOptions + if (*activep && *charptr == NULL) { + *charptr = tilde_expand_filename(arg, getuid()); + /* increase optional counter */ +- if (intptr != NULL) +- *intptr = *intptr + 1; ++ /* DEAD CODE intptr is still NULL ;) ++ if (intptr != NULL) ++ *intptr = *intptr + 1; */ + } + break; + +diff -up openssh-6.1p1/serverloop.c.coverity openssh-6.1p1/serverloop.c +--- openssh-6.1p1/serverloop.c.coverity 2012-06-20 14:31:27.000000000 +0200 ++++ openssh-6.1p1/serverloop.c 2012-09-14 21:16:41.294906638 +0200 +@@ -147,13 +147,13 @@ notify_setup(void) + static void + notify_parent(void) + { +- if (notify_pipe[1] != -1) ++ if (notify_pipe[1] >= 0) + write(notify_pipe[1], "", 1); + } + static void + notify_prepare(fd_set *readset) + { +- if (notify_pipe[0] != -1) ++ if (notify_pipe[0] >= 0) + FD_SET(notify_pipe[0], readset); + } + static void +@@ -161,8 +161,8 @@ notify_done(fd_set *readset) + { + char c; + +- if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset)) +- while (read(notify_pipe[0], &c, 1) != -1) ++ if (notify_pipe[0] >= 0 && FD_ISSET(notify_pipe[0], readset)) ++ while (read(notify_pipe[0], &c, 1) >= 0) + debug2("notify_done: reading"); + } + +@@ -336,7 +336,7 @@ wait_until_can_do_something(fd_set **rea + * If we have buffered data, try to write some of that data + * to the program. + */ +- if (fdin != -1 && buffer_len(&stdin_buffer) > 0) ++ if (fdin >= 0 && buffer_len(&stdin_buffer) > 0) + FD_SET(fdin, *writesetp); + } + notify_prepare(*readsetp); +@@ -476,7 +476,7 @@ process_output(fd_set *writeset) + int len; + + /* Write buffered data to program stdin. */ +- if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) { ++ if (!compat20 && fdin >= 0 && FD_ISSET(fdin, writeset)) { + data = buffer_ptr(&stdin_buffer); + dlen = buffer_len(&stdin_buffer); + len = write(fdin, data, dlen); +@@ -589,7 +589,7 @@ server_loop(pid_t pid, int fdin_arg, int + set_nonblock(fdin); + set_nonblock(fdout); + /* we don't have stderr for interactive terminal sessions, see below */ +- if (fderr != -1) ++ if (fderr >= 0) + set_nonblock(fderr); + + if (!(datafellows & SSH_BUG_IGNOREMSG) && isatty(fdin)) +@@ -613,7 +613,7 @@ server_loop(pid_t pid, int fdin_arg, int + max_fd = MAX(connection_in, connection_out); + max_fd = MAX(max_fd, fdin); + max_fd = MAX(max_fd, fdout); +- if (fderr != -1) ++ if (fderr >= 0) + max_fd = MAX(max_fd, fderr); + #endif + +@@ -643,7 +643,7 @@ server_loop(pid_t pid, int fdin_arg, int + * If we have received eof, and there is no more pending + * input data, cause a real eof by closing fdin. + */ +- if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) { ++ if (stdin_eof && fdin >= 0 && buffer_len(&stdin_buffer) == 0) { + if (fdin != fdout) + close(fdin); + else +@@ -741,15 +741,15 @@ server_loop(pid_t pid, int fdin_arg, int + buffer_free(&stderr_buffer); + + /* Close the file descriptors. */ +- if (fdout != -1) ++ if (fdout >= 0) + close(fdout); + fdout = -1; + fdout_eof = 1; +- if (fderr != -1) ++ if (fderr >= 0) + close(fderr); + fderr = -1; + fderr_eof = 1; +- if (fdin != -1) ++ if (fdin >= 0) + close(fdin); + fdin = -1; + +@@ -943,7 +943,7 @@ server_input_window_size(int type, u_int + + debug("Window change received."); + packet_check_eom(); +- if (fdin != -1) ++ if (fdin >= 0) + pty_change_window_size(fdin, row, col, xpixel, ypixel); + } + +@@ -996,7 +996,7 @@ server_request_tun(void) + } + + tun = packet_get_int(); +- if (forced_tun_device != -1) { ++ if (forced_tun_device >= 0) { + if (tun != SSH_TUNID_ANY && forced_tun_device != tun) + goto done; + tun = forced_tun_device; +diff -up openssh-6.1p1/sftp.c.coverity openssh-6.1p1/sftp.c +--- openssh-6.1p1/sftp.c.coverity 2012-06-30 00:33:32.000000000 +0200 ++++ openssh-6.1p1/sftp.c 2012-09-14 21:16:41.297906653 +0200 +@@ -206,7 +206,7 @@ killchild(int signo) + { + if (sshpid > 1) { + kill(sshpid, SIGTERM); +- waitpid(sshpid, NULL, 0); ++ (void) waitpid(sshpid, NULL, 0); + } + + _exit(1); +@@ -316,7 +316,7 @@ local_do_ls(const char *args) + + /* Strip one path (usually the pwd) from the start of another */ + static char * +-path_strip(char *path, char *strip) ++path_strip(const char *path, const char *strip) + { + size_t len; + +@@ -334,7 +334,7 @@ path_strip(char *path, char *strip) + } + + static char * +-make_absolute(char *p, char *pwd) ++make_absolute(char *p, const char *pwd) + { + char *abs_str; + +@@ -482,7 +482,7 @@ parse_df_flags(const char *cmd, char **a + } + + static int +-is_dir(char *path) ++is_dir(const char *path) + { + struct stat sb; + +@@ -494,7 +494,7 @@ is_dir(char *path) + } + + static int +-remote_is_dir(struct sftp_conn *conn, char *path) ++remote_is_dir(struct sftp_conn *conn, const char *path) + { + Attrib *a; + +@@ -508,7 +508,7 @@ remote_is_dir(struct sftp_conn *conn, ch + + /* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */ + static int +-pathname_is_dir(char *pathname) ++pathname_is_dir(const char *pathname) + { + size_t l = strlen(pathname); + +@@ -516,7 +516,7 @@ pathname_is_dir(char *pathname) + } + + static int +-process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, ++process_get(struct sftp_conn *conn, const char *src, const char *dst, const char *pwd, + int pflag, int rflag) + { + char *abs_src = NULL; +@@ -590,7 +590,7 @@ out: + } + + static int +-process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, ++process_put(struct sftp_conn *conn, const char *src, const char *dst, const char *pwd, + int pflag, int rflag) + { + char *tmp_dst = NULL; +@@ -695,7 +695,7 @@ sdirent_comp(const void *aa, const void + + /* sftp ls.1 replacement for directories */ + static int +-do_ls_dir(struct sftp_conn *conn, char *path, char *strip_path, int lflag) ++do_ls_dir(struct sftp_conn *conn, const char *path, const char *strip_path, int lflag) + { + int n; + u_int c = 1, colspace = 0, columns = 1; +@@ -780,7 +780,7 @@ do_ls_dir(struct sftp_conn *conn, char * + + /* sftp ls.1 replacement which handles path globs */ + static int +-do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path, ++do_globbed_ls(struct sftp_conn *conn, const char *path, const char *strip_path, + int lflag) + { + char *fname, *lname; +@@ -861,7 +861,7 @@ do_globbed_ls(struct sftp_conn *conn, ch + } + + static int +-do_df(struct sftp_conn *conn, char *path, int hflag, int iflag) ++do_df(struct sftp_conn *conn, const char *path, int hflag, int iflag) + { + struct sftp_statvfs st; + char s_used[FMT_SCALED_STRSIZE]; +diff -up openssh-6.1p1/sftp-client.c.coverity openssh-6.1p1/sftp-client.c +--- openssh-6.1p1/sftp-client.c.coverity 2012-07-02 14:15:39.000000000 +0200 ++++ openssh-6.1p1/sftp-client.c 2012-09-14 21:18:16.891332281 +0200 +@@ -149,7 +149,7 @@ get_msg(struct sftp_conn *conn, Buffer * + } + + static void +-send_string_request(struct sftp_conn *conn, u_int id, u_int code, char *s, ++send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s, + u_int len) + { + Buffer msg; +@@ -165,7 +165,7 @@ send_string_request(struct sftp_conn *co + + static void + send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, +- char *s, u_int len, Attrib *a) ++ const char *s, u_int len, Attrib *a) + { + Buffer msg; + +@@ -422,7 +422,7 @@ sftp_proto_version(struct sftp_conn *con + } + + int +-do_close(struct sftp_conn *conn, char *handle, u_int handle_len) ++do_close(struct sftp_conn *conn, const char *handle, u_int handle_len) + { + u_int id, status; + Buffer msg; +@@ -447,7 +447,7 @@ do_close(struct sftp_conn *conn, char *h + + + static int +-do_lsreaddir(struct sftp_conn *conn, char *path, int printflag, ++do_lsreaddir(struct sftp_conn *conn, const char *path, int printflag, + SFTP_DIRENT ***dir) + { + Buffer msg; +@@ -572,7 +572,7 @@ do_lsreaddir(struct sftp_conn *conn, cha + } + + int +-do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir) ++do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir) + { + return(do_lsreaddir(conn, path, 0, dir)); + } +@@ -590,7 +590,7 @@ void free_sftp_dirents(SFTP_DIRENT **s) + } + + int +-do_rm(struct sftp_conn *conn, char *path) ++do_rm(struct sftp_conn *conn, const char *path) + { + u_int status, id; + +@@ -605,7 +605,7 @@ do_rm(struct sftp_conn *conn, char *path + } + + int +-do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int printflag) ++do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int printflag) + { + u_int status, id; + +@@ -621,7 +621,7 @@ do_mkdir(struct sftp_conn *conn, char *p + } + + int +-do_rmdir(struct sftp_conn *conn, char *path) ++do_rmdir(struct sftp_conn *conn, const char *path) + { + u_int status, id; + +@@ -637,7 +637,7 @@ do_rmdir(struct sftp_conn *conn, char *p + } + + Attrib * +-do_stat(struct sftp_conn *conn, char *path, int quiet) ++do_stat(struct sftp_conn *conn, const char *path, int quiet) + { + u_int id; + +@@ -651,7 +651,7 @@ do_stat(struct sftp_conn *conn, char *pa + } + + Attrib * +-do_lstat(struct sftp_conn *conn, char *path, int quiet) ++do_lstat(struct sftp_conn *conn, const char *path, int quiet) + { + u_int id; + +@@ -685,7 +685,7 @@ do_fstat(struct sftp_conn *conn, char *h + #endif + + int +-do_setstat(struct sftp_conn *conn, char *path, Attrib *a) ++do_setstat(struct sftp_conn *conn, const char *path, Attrib *a) + { + u_int status, id; + +@@ -702,7 +702,7 @@ do_setstat(struct sftp_conn *conn, char + } + + int +-do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len, ++do_fsetstat(struct sftp_conn *conn, const char *handle, u_int handle_len, + Attrib *a) + { + u_int status, id; +@@ -719,7 +719,7 @@ do_fsetstat(struct sftp_conn *conn, char + } + + char * +-do_realpath(struct sftp_conn *conn, char *path) ++do_realpath(struct sftp_conn *conn, const char *path) + { + Buffer msg; + u_int type, expected_id, count, id; +@@ -768,7 +768,7 @@ do_realpath(struct sftp_conn *conn, char + } + + int +-do_rename(struct sftp_conn *conn, char *oldpath, char *newpath) ++do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath) + { + Buffer msg; + u_int status, id; +@@ -802,7 +802,7 @@ do_rename(struct sftp_conn *conn, char * + } + + int +-do_hardlink(struct sftp_conn *conn, char *oldpath, char *newpath) ++do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) + { + Buffer msg; + u_int status, id; +@@ -835,7 +835,7 @@ do_hardlink(struct sftp_conn *conn, char + } + + int +-do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath) ++do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) + { + Buffer msg; + u_int status, id; +@@ -987,7 +987,7 @@ send_read_request(struct sftp_conn *conn + } + + int +-do_download(struct sftp_conn *conn, char *remote_path, char *local_path, ++do_download(struct sftp_conn *conn, const char *remote_path, const char *local_path, + Attrib *a, int pflag) + { + Attrib junk; +@@ -1226,7 +1226,7 @@ do_download(struct sftp_conn *conn, char + } + + static int +-download_dir_internal(struct sftp_conn *conn, char *src, char *dst, ++download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, + Attrib *dirattrib, int pflag, int printflag, int depth) + { + int i, ret = 0; +@@ -1316,7 +1316,7 @@ download_dir_internal(struct sftp_conn * + } + + int +-download_dir(struct sftp_conn *conn, char *src, char *dst, ++download_dir(struct sftp_conn *conn, const char *src, const char *dst, + Attrib *dirattrib, int pflag, int printflag) + { + char *src_canon; +@@ -1334,7 +1334,7 @@ download_dir(struct sftp_conn *conn, cha + } + + int +-do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, ++do_upload(struct sftp_conn *conn, const char *local_path, const char *remote_path, + int pflag) + { + int local_fd; +@@ -1517,7 +1517,7 @@ do_upload(struct sftp_conn *conn, char * + } + + static int +-upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, ++upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, + int pflag, int printflag, int depth) + { + int ret = 0, status; +@@ -1608,7 +1608,7 @@ upload_dir_internal(struct sftp_conn *co + } + + int +-upload_dir(struct sftp_conn *conn, char *src, char *dst, int printflag, ++upload_dir(struct sftp_conn *conn, const char *src, const char *dst, int printflag, + int pflag) + { + char *dst_canon; +@@ -1625,7 +1625,7 @@ upload_dir(struct sftp_conn *conn, char + } + + char * +-path_append(char *p1, char *p2) ++path_append(const char *p1, const char *p2) + { + char *ret; + size_t len = strlen(p1) + strlen(p2) + 2; +diff -up openssh-6.1p1/sftp-client.h.coverity openssh-6.1p1/sftp-client.h +--- openssh-6.1p1/sftp-client.h.coverity 2010-12-04 23:02:48.000000000 +0100 ++++ openssh-6.1p1/sftp-client.h 2012-09-14 21:16:41.301906674 +0200 +@@ -56,49 +56,49 @@ struct sftp_conn *do_init(int, int, u_in + u_int sftp_proto_version(struct sftp_conn *); + + /* Close file referred to by 'handle' */ +-int do_close(struct sftp_conn *, char *, u_int); ++int do_close(struct sftp_conn *, const char *, u_int); + + /* Read contents of 'path' to NULL-terminated array 'dir' */ +-int do_readdir(struct sftp_conn *, char *, SFTP_DIRENT ***); ++int do_readdir(struct sftp_conn *, const char *, SFTP_DIRENT ***); + + /* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from do_readdir) */ + void free_sftp_dirents(SFTP_DIRENT **); + + /* Delete file 'path' */ +-int do_rm(struct sftp_conn *, char *); ++int do_rm(struct sftp_conn *, const char *); + + /* Create directory 'path' */ +-int do_mkdir(struct sftp_conn *, char *, Attrib *, int); ++int do_mkdir(struct sftp_conn *, const char *, Attrib *, int); + + /* Remove directory 'path' */ +-int do_rmdir(struct sftp_conn *, char *); ++int do_rmdir(struct sftp_conn *, const char *); + + /* Get file attributes of 'path' (follows symlinks) */ +-Attrib *do_stat(struct sftp_conn *, char *, int); ++Attrib *do_stat(struct sftp_conn *, const char *, int); + + /* Get file attributes of 'path' (does not follow symlinks) */ +-Attrib *do_lstat(struct sftp_conn *, char *, int); ++Attrib *do_lstat(struct sftp_conn *, const char *, int); + + /* Set file attributes of 'path' */ +-int do_setstat(struct sftp_conn *, char *, Attrib *); ++int do_setstat(struct sftp_conn *, const char *, Attrib *); + + /* Set file attributes of open file 'handle' */ +-int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *); ++int do_fsetstat(struct sftp_conn *, const char *, u_int, Attrib *); + + /* Canonicalise 'path' - caller must free result */ +-char *do_realpath(struct sftp_conn *, char *); ++char *do_realpath(struct sftp_conn *, const char *); + + /* Get statistics for filesystem hosting file at "path" */ + int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int); + + /* Rename 'oldpath' to 'newpath' */ +-int do_rename(struct sftp_conn *, char *, char *); ++int do_rename(struct sftp_conn *, const char *, const char *); + + /* Link 'oldpath' to 'newpath' */ +-int do_hardlink(struct sftp_conn *, char *, char *); ++int do_hardlink(struct sftp_conn *, const char *, const char *); + +-/* Rename 'oldpath' to 'newpath' */ +-int do_symlink(struct sftp_conn *, char *, char *); ++/* Symlink 'oldpath' to 'newpath' */ ++int do_symlink(struct sftp_conn *, const char *, const char *); + + /* XXX: add callbacks to do_download/do_upload so we can do progress meter */ + +@@ -106,27 +106,27 @@ int do_symlink(struct sftp_conn *, char + * Download 'remote_path' to 'local_path'. Preserve permissions and times + * if 'pflag' is set + */ +-int do_download(struct sftp_conn *, char *, char *, Attrib *, int); ++int do_download(struct sftp_conn *, const char *, const char *, Attrib *, int); + + /* + * Recursively download 'remote_directory' to 'local_directory'. Preserve + * times if 'pflag' is set + */ +-int download_dir(struct sftp_conn *, char *, char *, Attrib *, int, int); ++int download_dir(struct sftp_conn *, const char *, const char *, Attrib *, int, int); + + /* + * Upload 'local_path' to 'remote_path'. Preserve permissions and times + * if 'pflag' is set + */ +-int do_upload(struct sftp_conn *, char *, char *, int); ++int do_upload(struct sftp_conn *, const char *, const char *, int); + + /* + * Recursively upload 'local_directory' to 'remote_directory'. Preserve + * times if 'pflag' is set + */ +-int upload_dir(struct sftp_conn *, char *, char *, int, int); ++int upload_dir(struct sftp_conn *, const char *, const char *, int, int); + + /* Concatenate paths, taking care of slashes. Caller must free result. */ +-char *path_append(char *, char *); ++char *path_append(const char *, const char *); + + #endif +diff -up openssh-6.1p1/ssh-agent.c.coverity openssh-6.1p1/ssh-agent.c +--- openssh-6.1p1/ssh-agent.c.coverity 2011-06-03 06:14:16.000000000 +0200 ++++ openssh-6.1p1/ssh-agent.c 2012-09-14 21:16:41.303906683 +0200 +@@ -1147,8 +1147,8 @@ main(int ac, char **av) + sanitise_stdfd(); + + /* drop */ +- setegid(getgid()); +- setgid(getgid()); ++ (void) setegid(getgid()); ++ (void) setgid(getgid()); + + #if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) + /* Disable ptrace on Linux without sgid bit */ +diff -up openssh-6.1p1/sshd.c.coverity openssh-6.1p1/sshd.c +--- openssh-6.1p1/sshd.c.coverity 2012-07-31 04:21:34.000000000 +0200 ++++ openssh-6.1p1/sshd.c 2012-09-14 21:16:41.307906705 +0200 +@@ -682,8 +682,10 @@ privsep_preauth(Authctxt *authctxt) + if (getuid() == 0 || geteuid() == 0) + privsep_preauth_child(); + setproctitle("%s", "[net]"); +- if (box != NULL) ++ if (box != NULL) { + ssh_sandbox_child(box); ++ xfree(box); ++ } + + return 0; + } +@@ -1311,6 +1313,9 @@ server_accept_loop(int *sock_in, int *so + if (num_listen_socks < 0) + break; + } ++ ++ if (fdset != NULL) ++ xfree(fdset); + } + + +@@ -1768,7 +1773,7 @@ main(int ac, char **av) + + /* Chdir to the root directory so that the current disk can be + unmounted if desired. */ +- chdir("/"); ++ (void) chdir("/"); + + /* ignore SIGPIPE */ + signal(SIGPIPE, SIG_IGN); diff --git a/openssh-6.1p1-gsskex.patch b/openssh-6.1p1-gsskex.patch new file mode 100644 index 0000000..b580a6d --- /dev/null +++ b/openssh-6.1p1-gsskex.patch @@ -0,0 +1,3027 @@ +diff -up openssh-6.1p1/auth-krb5.c.gsskex openssh-6.1p1/auth-krb5.c +--- openssh-6.1p1/auth-krb5.c.gsskex 2012-04-26 01:52:15.000000000 +0200 ++++ openssh-6.1p1/auth-krb5.c 2012-09-14 21:07:19.695203206 +0200 +@@ -50,6 +50,7 @@ + #include + #include + #include ++#include + #include + + extern ServerOptions options; +@@ -170,8 +171,13 @@ auth_krb5_password(Authctxt *authctxt, c + + len = strlen(authctxt->krb5_ticket_file) + 6; + authctxt->krb5_ccname = xmalloc(len); +- snprintf(authctxt->krb5_ccname, len, "FILE:%s", ++#ifdef USE_CCAPI ++ snprintf(authctxt->krb5_ccname, len, "API:%s", + authctxt->krb5_ticket_file); ++#else ++ snprintf(authctxt->krb5_ccname, len, "DIR:%s", ++ authctxt->krb5_ticket_file); ++#endif + + #ifdef USE_PAM + if (options.use_pam) +@@ -208,10 +214,33 @@ auth_krb5_password(Authctxt *authctxt, c + void + krb5_cleanup_proc(Authctxt *authctxt) + { ++ struct stat krb5_ccname_stat; ++ char krb5_ccname[128], *krb5_ccname_dir_end; ++ + debug("krb5_cleanup_proc called"); + if (authctxt->krb5_fwd_ccache) { + krb5_cc_destroy(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache); + authctxt->krb5_fwd_ccache = NULL; ++ ++ /* assume ticket cache type DIR - DIR::/tmp/krb5cc_876600005_T9eDKSQvzb/tkt */ ++ strncpy(krb5_ccname, authctxt->krb5_ccname + strlen("DIR::"), sizeof(krb5_ccname) - 10); ++ ++ krb5_ccname_dir_end = strrchr(krb5_ccname, '/'); ++ if (krb5_ccname_dir_end != NULL) { ++ strcpy(krb5_ccname_dir_end, "/primary"); ++ ++ if (stat(krb5_ccname, &krb5_ccname_stat) == 0) { ++ if (unlink(krb5_ccname) == 0) { ++ *krb5_ccname_dir_end = '\0'; ++ if (rmdir(krb5_ccname) == -1) ++ debug("cache dir '%s' remove failed: %s", krb5_ccname, strerror(errno)); ++ } ++ else ++ debug("cache primary file '%s', remove failed: %s", ++ krb5_ccname, strerror(errno) ++ ); ++ } ++ } + } + if (authctxt->krb5_user) { + krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user); +@@ -226,31 +255,37 @@ krb5_cleanup_proc(Authctxt *authctxt) + #ifndef HEIMDAL + krb5_error_code + ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { +- int tmpfd, ret, oerrno; +- char ccname[40]; ++ int ret, oerrno; ++ char ccname[128]; + mode_t old_umask; ++#ifdef USE_CCAPI ++ char cctemplate[] = "API:krb5cc_%d"; ++#else ++ char cctemplate[] = "DIR:/tmp/krb5cc_%d_XXXXXXXXXX"; ++ char *tmpdir; ++#endif + + ret = snprintf(ccname, sizeof(ccname), +- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); ++ cctemplate, geteuid()); + if (ret < 0 || (size_t)ret >= sizeof(ccname)) + return ENOMEM; + +- old_umask = umask(0177); +- tmpfd = mkstemp(ccname + strlen("FILE:")); ++#ifndef USE_CCAPI ++ old_umask = umask(0077); ++ tmpdir = mkdtemp(ccname + strlen("DIR:")); + oerrno = errno; + umask(old_umask); +- if (tmpfd == -1) { +- logit("mkstemp(): %.100s", strerror(oerrno)); ++ if (tmpdir == NULL) { ++ logit("mkdtemp(): %.100s", strerror(oerrno)); + return oerrno; + } + +- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { ++ if (chmod(tmpdir, S_IRUSR | S_IWUSR | S_IXUSR) == -1) { + oerrno = errno; +- logit("fchmod(): %.100s", strerror(oerrno)); +- close(tmpfd); ++ logit("chmod(): %.100s", strerror(oerrno)); + return oerrno; + } +- close(tmpfd); ++#endif + + return (krb5_cc_resolve(ctx, ccname, ccache)); + } +diff -up openssh-6.1p1/auth2.c.gsskex openssh-6.1p1/auth2.c +--- openssh-6.1p1/auth2.c.gsskex 2012-09-14 20:57:55.291263269 +0200 ++++ openssh-6.1p1/auth2.c 2012-09-14 20:57:55.853266860 +0200 +@@ -69,6 +69,7 @@ extern Authmethod method_passwd; + extern Authmethod method_kbdint; + extern Authmethod method_hostbased; + #ifdef GSSAPI ++extern Authmethod method_gsskeyex; + extern Authmethod method_gssapi; + #endif + #ifdef JPAKE +@@ -79,6 +80,7 @@ Authmethod *authmethods[] = { + &method_none, + &method_pubkey, + #ifdef GSSAPI ++ &method_gsskeyex, + &method_gssapi, + #endif + #ifdef JPAKE +diff -up openssh-6.1p1/auth2-gss.c.gsskex openssh-6.1p1/auth2-gss.c +--- openssh-6.1p1/auth2-gss.c.gsskex 2012-09-14 20:57:55.292263276 +0200 ++++ openssh-6.1p1/auth2-gss.c 2012-09-14 20:57:55.855266873 +0200 +@@ -52,6 +52,40 @@ static void input_gssapi_mic(int type, u + static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); + static void input_gssapi_errtok(int, u_int32_t, void *); + ++/* ++ * The 'gssapi_keyex' userauth mechanism. ++ */ ++static int ++userauth_gsskeyex(Authctxt *authctxt) ++{ ++ int authenticated = 0; ++ Buffer b; ++ gss_buffer_desc mic, gssbuf; ++ u_int len; ++ ++ mic.value = packet_get_string(&len); ++ mic.length = len; ++ ++ packet_check_eom(); ++ ++ ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service, ++ "gssapi-keyex"); ++ ++ gssbuf.value = buffer_ptr(&b); ++ gssbuf.length = buffer_len(&b); ++ ++ /* gss_kex_context is NULL with privsep, so we can't check it here */ ++ if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, ++ &gssbuf, &mic)))) ++ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, ++ authctxt->pw)); ++ ++ buffer_free(&b); ++ xfree(mic.value); ++ ++ return (authenticated); ++} ++ + /* + * We only support those mechanisms that we know about (ie ones that we know + * how to check local user kuserok and the like) +@@ -244,7 +278,8 @@ input_gssapi_exchange_complete(int type, + + packet_check_eom(); + +- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); ++ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, ++ authctxt->pw)); + + authctxt->postponed = 0; + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); +@@ -286,7 +321,8 @@ input_gssapi_mic(int type, u_int32_t ple + gssbuf.length = buffer_len(&b); + + if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) +- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); ++ authenticated = ++ PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw)); + else + logit("GSSAPI MIC check failed"); + +@@ -303,6 +339,12 @@ input_gssapi_mic(int type, u_int32_t ple + userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); + } + ++Authmethod method_gsskeyex = { ++ "gssapi-keyex", ++ userauth_gsskeyex, ++ &options.gss_authentication ++}; ++ + Authmethod method_gssapi = { + "gssapi-with-mic", + userauth_gssapi, +diff -up openssh-6.1p1/clientloop.c.gsskex openssh-6.1p1/clientloop.c +--- openssh-6.1p1/clientloop.c.gsskex 2012-09-14 20:57:54.862260529 +0200 ++++ openssh-6.1p1/clientloop.c 2012-09-14 20:57:55.861266911 +0200 +@@ -111,6 +111,10 @@ + #include "msg.h" + #include "roaming.h" + ++#ifdef GSSAPI ++#include "ssh-gss.h" ++#endif ++ + /* import options */ + extern Options options; + +@@ -1544,6 +1548,15 @@ client_loop(int have_pty, int escape_cha + /* Do channel operations unless rekeying in progress. */ + if (!rekeying) { + channel_after_select(readset, writeset); ++ ++#ifdef GSSAPI ++ if (options.gss_renewal_rekey && ++ ssh_gssapi_credentials_updated(GSS_C_NO_CONTEXT)) { ++ debug("credentials updated - forcing rekey"); ++ need_rekeying = 1; ++ } ++#endif ++ + if (need_rekeying || packet_need_rekeying()) { + debug("need rekeying"); + xxx_kex->done = 0; +diff -up openssh-6.1p1/configure.ac.gsskex openssh-6.1p1/configure.ac +--- openssh-6.1p1/configure.ac.gsskex 2012-09-14 20:57:55.756266240 +0200 ++++ openssh-6.1p1/configure.ac 2012-09-14 20:57:55.865266937 +0200 +@@ -545,6 +545,30 @@ main() { if (NSVersionOfRunTimeLibrary(" + [Use tunnel device compatibility to OpenBSD]) + AC_DEFINE([SSH_TUN_PREPEND_AF], [1], + [Prepend the address family to IP tunnel traffic]) ++ AC_MSG_CHECKING(if we have the Security Authorization Session API) ++ AC_TRY_COMPILE([#include ], ++ [SessionCreate(0, 0);], ++ [ac_cv_use_security_session_api="yes" ++ AC_DEFINE(USE_SECURITY_SESSION_API, 1, ++ [platform has the Security Authorization Session API]) ++ LIBS="$LIBS -framework Security" ++ AC_MSG_RESULT(yes)], ++ [ac_cv_use_security_session_api="no" ++ AC_MSG_RESULT(no)]) ++ AC_MSG_CHECKING(if we have an in-memory credentials cache) ++ AC_TRY_COMPILE( ++ [#include ], ++ [cc_context_t c; ++ (void) cc_initialize (&c, 0, NULL, NULL);], ++ [AC_DEFINE(USE_CCAPI, 1, ++ [platform uses an in-memory credentials cache]) ++ LIBS="$LIBS -framework Security" ++ AC_MSG_RESULT(yes) ++ if test "x$ac_cv_use_security_session_api" = "xno"; then ++ AC_MSG_ERROR(*** Need a security framework to use the credentials cache API ***) ++ fi], ++ [AC_MSG_RESULT(no)] ++ ) + m4_pattern_allow([AU_IPv]) + AC_CHECK_DECL([AU_IPv4], [], + AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) +diff -up openssh-6.1p1/gss-genr.c.gsskex openssh-6.1p1/gss-genr.c +--- openssh-6.1p1/gss-genr.c.gsskex 2009-06-22 08:11:07.000000000 +0200 ++++ openssh-6.1p1/gss-genr.c 2012-09-14 20:57:55.867266949 +0200 +@@ -1,7 +1,7 @@ + /* $OpenBSD: gss-genr.c,v 1.20 2009/06/22 05:39:28 dtucker Exp $ */ + + /* +- * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -39,12 +39,167 @@ + #include "buffer.h" + #include "log.h" + #include "ssh2.h" ++#include "cipher.h" ++#include "key.h" ++#include "kex.h" ++#include + + #include "ssh-gss.h" + + extern u_char *session_id2; + extern u_int session_id2_len; + ++typedef struct { ++ char *encoded; ++ gss_OID oid; ++} ssh_gss_kex_mapping; ++ ++/* ++ * XXX - It would be nice to find a more elegant way of handling the ++ * XXX passing of the key exchange context to the userauth routines ++ */ ++ ++Gssctxt *gss_kex_context = NULL; ++ ++static ssh_gss_kex_mapping *gss_enc2oid = NULL; ++ ++int ++ssh_gssapi_oid_table_ok() { ++ return (gss_enc2oid != NULL); ++} ++ ++/* ++ * Return a list of the gss-group1-sha1 mechanisms supported by this program ++ * ++ * We test mechanisms to ensure that we can use them, to avoid starting ++ * a key exchange with a bad mechanism ++ */ ++ ++char * ++ssh_gssapi_client_mechanisms(const char *host, const char *client) { ++ gss_OID_set gss_supported; ++ OM_uint32 min_status; ++ ++ if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported))) ++ return NULL; ++ ++ return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, ++ host, client)); ++} ++ ++char * ++ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, ++ const char *host, const char *client) { ++ Buffer buf; ++ size_t i; ++ int oidpos, enclen; ++ char *mechs, *encoded; ++ u_char digest[EVP_MAX_MD_SIZE]; ++ char deroid[2]; ++ const EVP_MD *evp_md = EVP_md5(); ++ EVP_MD_CTX md; ++ ++ if (gss_enc2oid != NULL) { ++ for (i = 0; gss_enc2oid[i].encoded != NULL; i++) ++ xfree(gss_enc2oid[i].encoded); ++ xfree(gss_enc2oid); ++ } ++ ++ gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) * ++ (gss_supported->count + 1)); ++ ++ buffer_init(&buf); ++ ++ oidpos = 0; ++ for (i = 0; i < gss_supported->count; i++) { ++ if (gss_supported->elements[i].length < 128 && ++ (*check)(NULL, &(gss_supported->elements[i]), host, client)) { ++ ++ deroid[0] = SSH_GSS_OIDTYPE; ++ deroid[1] = gss_supported->elements[i].length; ++ ++ EVP_DigestInit(&md, evp_md); ++ EVP_DigestUpdate(&md, deroid, 2); ++ EVP_DigestUpdate(&md, ++ gss_supported->elements[i].elements, ++ gss_supported->elements[i].length); ++ EVP_DigestFinal(&md, digest, NULL); ++ ++ encoded = xmalloc(EVP_MD_size(evp_md) * 2); ++ enclen = __b64_ntop(digest, EVP_MD_size(evp_md), ++ encoded, EVP_MD_size(evp_md) * 2); ++ ++ if (oidpos != 0) ++ buffer_put_char(&buf, ','); ++ ++ buffer_append(&buf, KEX_GSS_GEX_SHA1_ID, ++ sizeof(KEX_GSS_GEX_SHA1_ID) - 1); ++ buffer_append(&buf, encoded, enclen); ++ buffer_put_char(&buf, ','); ++ buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID, ++ sizeof(KEX_GSS_GRP1_SHA1_ID) - 1); ++ buffer_append(&buf, encoded, enclen); ++ buffer_put_char(&buf, ','); ++ buffer_append(&buf, KEX_GSS_GRP14_SHA1_ID, ++ sizeof(KEX_GSS_GRP14_SHA1_ID) - 1); ++ buffer_append(&buf, encoded, enclen); ++ ++ gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]); ++ gss_enc2oid[oidpos].encoded = encoded; ++ oidpos++; ++ } ++ } ++ gss_enc2oid[oidpos].oid = NULL; ++ gss_enc2oid[oidpos].encoded = NULL; ++ ++ buffer_put_char(&buf, '\0'); ++ ++ mechs = xmalloc(buffer_len(&buf)); ++ buffer_get(&buf, mechs, buffer_len(&buf)); ++ buffer_free(&buf); ++ ++ if (strlen(mechs) == 0) { ++ xfree(mechs); ++ mechs = NULL; ++ } ++ ++ return (mechs); ++} ++ ++gss_OID ++ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) { ++ int i = 0; ++ ++ switch (kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID)) ++ return GSS_C_NO_OID; ++ name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1; ++ break; ++ case KEX_GSS_GRP14_SHA1: ++ if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID)) ++ return GSS_C_NO_OID; ++ name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1; ++ break; ++ case KEX_GSS_GEX_SHA1: ++ if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID)) ++ return GSS_C_NO_OID; ++ name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1; ++ break; ++ default: ++ return GSS_C_NO_OID; ++ } ++ ++ while (gss_enc2oid[i].encoded != NULL && ++ strcmp(name, gss_enc2oid[i].encoded) != 0) ++ i++; ++ ++ if (gss_enc2oid[i].oid != NULL && ctx != NULL) ++ ssh_gssapi_set_oid(ctx, gss_enc2oid[i].oid); ++ ++ return gss_enc2oid[i].oid; ++} ++ + /* Check that the OID in a data stream matches that in the context */ + int + ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) +@@ -197,7 +352,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int de + } + + ctx->major = gss_init_sec_context(&ctx->minor, +- GSS_C_NO_CREDENTIAL, &ctx->context, ctx->name, ctx->oid, ++ ctx->client_creds, &ctx->context, ctx->name, ctx->oid, + GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, + 0, NULL, recv_tok, NULL, send_tok, flags, NULL); + +@@ -227,8 +382,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, con + } + + OM_uint32 ++ssh_gssapi_client_identity(Gssctxt *ctx, const char *name) ++{ ++ gss_buffer_desc gssbuf; ++ gss_name_t gssname; ++ OM_uint32 status; ++ gss_OID_set oidset; ++ ++ gssbuf.value = (void *) name; ++ gssbuf.length = strlen(gssbuf.value); ++ ++ gss_create_empty_oid_set(&status, &oidset); ++ gss_add_oid_set_member(&status, ctx->oid, &oidset); ++ ++ ctx->major = gss_import_name(&ctx->minor, &gssbuf, ++ GSS_C_NT_USER_NAME, &gssname); ++ ++ if (!ctx->major) ++ ctx->major = gss_acquire_cred(&ctx->minor, ++ gssname, 0, oidset, GSS_C_INITIATE, ++ &ctx->client_creds, NULL, NULL); ++ ++ gss_release_name(&status, &gssname); ++ gss_release_oid_set(&status, &oidset); ++ ++ if (ctx->major) ++ ssh_gssapi_error(ctx); ++ ++ return(ctx->major); ++} ++ ++OM_uint32 + ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) + { ++ if (ctx == NULL) ++ return -1; ++ + if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, + GSS_C_QOP_DEFAULT, buffer, hash))) + ssh_gssapi_error(ctx); +@@ -236,6 +425,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer + return (ctx->major); + } + ++/* Priviledged when used by server */ ++OM_uint32 ++ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) ++{ ++ if (ctx == NULL) ++ return -1; ++ ++ ctx->major = gss_verify_mic(&ctx->minor, ctx->context, ++ gssbuf, gssmic, NULL); ++ ++ return (ctx->major); ++} ++ + void + ssh_gssapi_buildmic(Buffer *b, const char *user, const char *service, + const char *context) +@@ -249,11 +451,16 @@ ssh_gssapi_buildmic(Buffer *b, const cha + } + + int +-ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) ++ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, ++ const char *client) + { + gss_buffer_desc token = GSS_C_EMPTY_BUFFER; + OM_uint32 major, minor; + gss_OID_desc spnego_oid = {6, (void *)"\x2B\x06\x01\x05\x05\x02"}; ++ Gssctxt *intctx = NULL; ++ ++ if (ctx == NULL) ++ ctx = &intctx; + + /* RFC 4462 says we MUST NOT do SPNEGO */ + if (oid->length == spnego_oid.length && +@@ -263,6 +470,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx + ssh_gssapi_build_ctx(ctx); + ssh_gssapi_set_oid(*ctx, oid); + major = ssh_gssapi_import_name(*ctx, host); ++ ++ if (!GSS_ERROR(major) && client) ++ major = ssh_gssapi_client_identity(*ctx, client); ++ + if (!GSS_ERROR(major)) { + major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, + NULL); +@@ -272,10 +483,67 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx + GSS_C_NO_BUFFER); + } + +- if (GSS_ERROR(major)) ++ if (GSS_ERROR(major) || intctx != NULL) + ssh_gssapi_delete_ctx(ctx); + + return (!GSS_ERROR(major)); + } + ++int ++ssh_gssapi_credentials_updated(Gssctxt *ctxt) { ++ static gss_name_t saved_name = GSS_C_NO_NAME; ++ static OM_uint32 saved_lifetime = 0; ++ static gss_OID saved_mech = GSS_C_NO_OID; ++ static gss_name_t name; ++ static OM_uint32 last_call = 0; ++ OM_uint32 lifetime, now, major, minor; ++ int equal; ++ gss_cred_usage_t usage = GSS_C_INITIATE; ++ ++ now = time(NULL); ++ ++ if (ctxt) { ++ debug("Rekey has happened - updating saved versions"); ++ ++ if (saved_name != GSS_C_NO_NAME) ++ gss_release_name(&minor, &saved_name); ++ ++ major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, ++ &saved_name, &saved_lifetime, NULL, NULL); ++ ++ if (!GSS_ERROR(major)) { ++ saved_mech = ctxt->oid; ++ saved_lifetime+= now; ++ } else { ++ /* Handle the error */ ++ } ++ return 0; ++ } ++ ++ if (now - last_call < 10) ++ return 0; ++ ++ last_call = now; ++ ++ if (saved_mech == GSS_C_NO_OID) ++ return 0; ++ ++ major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, ++ &name, &lifetime, NULL, NULL); ++ if (major == GSS_S_CREDENTIALS_EXPIRED) ++ return 0; ++ else if (GSS_ERROR(major)) ++ return 0; ++ ++ major = gss_compare_name(&minor, saved_name, name, &equal); ++ gss_release_name(&minor, &name); ++ if (GSS_ERROR(major)) ++ return 0; ++ ++ if (equal && (saved_lifetime < lifetime + now - 10)) ++ return 1; ++ ++ return 0; ++} ++ + #endif /* GSSAPI */ +diff -up openssh-6.1p1/gss-serv.c.gsskex openssh-6.1p1/gss-serv.c +--- openssh-6.1p1/gss-serv.c.gsskex 2011-08-05 22:16:46.000000000 +0200 ++++ openssh-6.1p1/gss-serv.c 2012-09-14 20:57:55.870266969 +0200 +@@ -45,15 +45,20 @@ + #include "channels.h" + #include "session.h" + #include "misc.h" ++#include "servconf.h" ++#include "uidswap.h" + + #include "ssh-gss.h" ++#include "monitor_wrap.h" ++ ++extern ServerOptions options; + + static ssh_gssapi_client gssapi_client = + { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, +- GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL}}; ++ GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, NULL, {NULL, NULL, NULL}, 0, 0}; + + ssh_gssapi_mech gssapi_null_mech = +- { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL}; ++ { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL}; + + #ifdef KRB5 + extern ssh_gssapi_mech gssapi_kerberos_mech; +@@ -81,25 +86,32 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx) + char lname[MAXHOSTNAMELEN]; + gss_OID_set oidset; + +- gss_create_empty_oid_set(&status, &oidset); +- gss_add_oid_set_member(&status, ctx->oid, &oidset); ++ if (options.gss_strict_acceptor) { ++ gss_create_empty_oid_set(&status, &oidset); ++ gss_add_oid_set_member(&status, ctx->oid, &oidset); ++ ++ if (gethostname(lname, MAXHOSTNAMELEN)) { ++ gss_release_oid_set(&status, &oidset); ++ return (-1); ++ } + +- if (gethostname(lname, MAXHOSTNAMELEN)) { +- gss_release_oid_set(&status, &oidset); +- return (-1); +- } ++ if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { ++ gss_release_oid_set(&status, &oidset); ++ return (ctx->major); ++ } ++ ++ if ((ctx->major = gss_acquire_cred(&ctx->minor, ++ ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, ++ NULL, NULL))) ++ ssh_gssapi_error(ctx); + +- if (GSS_ERROR(ssh_gssapi_import_name(ctx, lname))) { + gss_release_oid_set(&status, &oidset); + return (ctx->major); ++ } else { ++ ctx->name = GSS_C_NO_NAME; ++ ctx->creds = GSS_C_NO_CREDENTIAL; + } +- +- if ((ctx->major = gss_acquire_cred(&ctx->minor, +- ctx->name, 0, oidset, GSS_C_ACCEPT, &ctx->creds, NULL, NULL))) +- ssh_gssapi_error(ctx); +- +- gss_release_oid_set(&status, &oidset); +- return (ctx->major); ++ return GSS_S_COMPLETE; + } + + /* Privileged */ +@@ -114,6 +126,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss + } + + /* Unprivileged */ ++char * ++ssh_gssapi_server_mechanisms() { ++ gss_OID_set supported; ++ ++ ssh_gssapi_supported_oids(&supported); ++ return (ssh_gssapi_kex_mechs(supported, &ssh_gssapi_server_check_mech, ++ NULL, NULL)); ++} ++ ++/* Unprivileged */ ++int ++ssh_gssapi_server_check_mech(Gssctxt **dum, gss_OID oid, const char *data, ++ const char *dummy) { ++ Gssctxt *ctx = NULL; ++ int res; ++ ++ res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid))); ++ ssh_gssapi_delete_ctx(&ctx); ++ ++ return (res); ++} ++ ++/* Unprivileged */ + void + ssh_gssapi_supported_oids(gss_OID_set *oidset) + { +@@ -123,7 +158,9 @@ ssh_gssapi_supported_oids(gss_OID_set *o + gss_OID_set supported; + + gss_create_empty_oid_set(&min_status, oidset); +- gss_indicate_mechs(&min_status, &supported); ++ ++ if (GSS_ERROR(gss_indicate_mechs(&min_status, &supported))) ++ return; + + while (supported_mechs[i]->name != NULL) { + if (GSS_ERROR(gss_test_oid_set_member(&min_status, +@@ -249,8 +286,48 @@ OM_uint32 + ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) + { + int i = 0; ++ int equal = 0; ++ gss_name_t new_name = GSS_C_NO_NAME; ++ gss_buffer_desc ename = GSS_C_EMPTY_BUFFER; ++ ++ if (options.gss_store_rekey && client->used && ctx->client_creds) { ++ if (client->mech->oid.length != ctx->oid->length || ++ (memcmp(client->mech->oid.elements, ++ ctx->oid->elements, ctx->oid->length) !=0)) { ++ debug("Rekeyed credentials have different mechanism"); ++ return GSS_S_COMPLETE; ++ } ++ ++ if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, ++ ctx->client_creds, ctx->oid, &new_name, ++ NULL, NULL, NULL))) { ++ ssh_gssapi_error(ctx); ++ return (ctx->major); ++ } + +- gss_buffer_desc ename; ++ ctx->major = gss_compare_name(&ctx->minor, client->name, ++ new_name, &equal); ++ ++ if (GSS_ERROR(ctx->major)) { ++ ssh_gssapi_error(ctx); ++ return (ctx->major); ++ } ++ ++ if (!equal) { ++ debug("Rekeyed credentials have different name"); ++ return GSS_S_COMPLETE; ++ } ++ ++ debug("Marking rekeyed credentials for export"); ++ ++ gss_release_name(&ctx->minor, &client->name); ++ gss_release_cred(&ctx->minor, &client->creds); ++ client->name = new_name; ++ client->creds = ctx->client_creds; ++ ctx->client_creds = GSS_C_NO_CREDENTIAL; ++ client->updated = 1; ++ return GSS_S_COMPLETE; ++ } + + client->mech = NULL; + +@@ -265,6 +342,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g + if (client->mech == NULL) + return GSS_S_FAILURE; + ++ if (ctx->client_creds && ++ (ctx->major = gss_inquire_cred_by_mech(&ctx->minor, ++ ctx->client_creds, ctx->oid, &client->name, NULL, NULL, NULL))) { ++ ssh_gssapi_error(ctx); ++ return (ctx->major); ++ } ++ + if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, + &client->displayname, NULL))) { + ssh_gssapi_error(ctx); +@@ -282,6 +366,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g + return (ctx->major); + } + ++ gss_release_buffer(&ctx->minor, &ename); ++ + /* We can't copy this structure, so we just move the pointer to it */ + client->creds = ctx->client_creds; + ctx->client_creds = GSS_C_NO_CREDENTIAL; +@@ -292,11 +378,33 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g + void + ssh_gssapi_cleanup_creds(void) + { ++ struct stat krb5_ccname_stat; ++ char krb5_ccname[128], *krb5_ccname_dir_end; ++ + if (gssapi_client.store.filename != NULL) { + /* Unlink probably isn't sufficient */ + debug("removing gssapi cred file\"%s\"", + gssapi_client.store.filename); + unlink(gssapi_client.store.filename); ++ ++ /* Ticket cache: DIR::/tmp/krb5cc_876600005_T9eDKSQvzb/tkt */ ++ /* same code as in auth-krb5.c:krb5_cleanup_proc */ ++ strncpy(krb5_ccname, gssapi_client.store.filename, sizeof(krb5_ccname) - 10); ++ krb5_ccname_dir_end = strrchr(krb5_ccname, '/'); ++ if (krb5_ccname_dir_end != NULL) ++ strcpy(krb5_ccname_dir_end, "/primary"); ++ ++ if (stat(krb5_ccname, &krb5_ccname_stat) == 0) { ++ if (unlink(krb5_ccname) == 0) { ++ *krb5_ccname_dir_end = '\0'; ++ if (rmdir(krb5_ccname) == -1) ++ debug("cache dir '%s' remove failed: %s", krb5_ccname, strerror(errno)); ++ } ++ else ++ debug("cache primary file '%s', remove failed: %s", ++ krb5_ccname, strerror(errno) ++ ); ++ } + } + } + +@@ -329,7 +437,7 @@ ssh_gssapi_do_child(char ***envp, u_int + + /* Privileged */ + int +-ssh_gssapi_userok(char *user) ++ssh_gssapi_userok(char *user, struct passwd *pw) + { + OM_uint32 lmin; + +@@ -339,9 +447,11 @@ ssh_gssapi_userok(char *user) + return 0; + } + if (gssapi_client.mech && gssapi_client.mech->userok) +- if ((*gssapi_client.mech->userok)(&gssapi_client, user)) ++ if ((*gssapi_client.mech->userok)(&gssapi_client, user)) { ++ gssapi_client.used = 1; ++ gssapi_client.store.owner = pw; + return 1; +- else { ++ } else { + /* Destroy delegated credentials if userok fails */ + gss_release_buffer(&lmin, &gssapi_client.displayname); + gss_release_buffer(&lmin, &gssapi_client.exportedname); +@@ -354,14 +464,90 @@ ssh_gssapi_userok(char *user) + return (0); + } + +-/* Privileged */ +-OM_uint32 +-ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) ++/* These bits are only used for rekeying. The unpriviledged child is running ++ * as the user, the monitor is root. ++ * ++ * In the child, we want to : ++ * *) Ask the monitor to store our credentials into the store we specify ++ * *) If it succeeds, maybe do a PAM update ++ */ ++ ++/* Stuff for PAM */ ++ ++#ifdef USE_PAM ++static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, ++ struct pam_response **resp, void *data) + { +- ctx->major = gss_verify_mic(&ctx->minor, ctx->context, +- gssbuf, gssmic, NULL); ++ return (PAM_CONV_ERR); ++} ++#endif + +- return (ctx->major); ++void ++ssh_gssapi_rekey_creds() { ++ int ok; ++ int ret; ++#ifdef USE_PAM ++ pam_handle_t *pamh = NULL; ++ struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL}; ++ char *envstr; ++#endif ++ ++ if (gssapi_client.store.filename == NULL && ++ gssapi_client.store.envval == NULL && ++ gssapi_client.store.envvar == NULL) ++ return; ++ ++ ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store)); ++ ++ if (!ok) ++ return; ++ ++ debug("Rekeyed credentials stored successfully"); ++ ++ /* Actually managing to play with the ssh pam stack from here will ++ * be next to impossible. In any case, we may want different options ++ * for rekeying. So, use our own :) ++ */ ++#ifdef USE_PAM ++ if (!use_privsep) { ++ debug("Not even going to try and do PAM with privsep disabled"); ++ return; ++ } ++ ++ ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name, ++ &pamconv, &pamh); ++ if (ret) ++ return; ++ ++ xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, ++ gssapi_client.store.envval); ++ ++ ret = pam_putenv(pamh, envstr); ++ if (!ret) ++ pam_setcred(pamh, PAM_REINITIALIZE_CRED); ++ pam_end(pamh, PAM_SUCCESS); ++#endif ++} ++ ++int ++ssh_gssapi_update_creds(ssh_gssapi_ccache *store) { ++ int ok = 0; ++ ++ /* Check we've got credentials to store */ ++ if (!gssapi_client.updated) ++ return 0; ++ ++ gssapi_client.updated = 0; ++ ++ temporarily_use_uid(gssapi_client.store.owner); ++ if (gssapi_client.mech && gssapi_client.mech->updatecreds) ++ ok = (*gssapi_client.mech->updatecreds)(store, &gssapi_client); ++ else ++ debug("No update function for this mechanism"); ++ ++ restore_uid(); ++ ++ return ok; + } + + #endif +diff -up openssh-6.1p1/gss-serv-krb5.c.gsskex openssh-6.1p1/gss-serv-krb5.c +--- openssh-6.1p1/gss-serv-krb5.c.gsskex 2006-09-01 07:38:36.000000000 +0200 ++++ openssh-6.1p1/gss-serv-krb5.c 2012-09-14 20:57:55.872266981 +0200 +@@ -1,7 +1,7 @@ + /* $OpenBSD: gss-serv-krb5.c,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */ + + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -120,6 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + krb5_principal princ; + OM_uint32 maj_status, min_status; + int len; ++ const char *new_ccname; + + if (client->creds == NULL) { + debug("No credentials stored"); +@@ -168,11 +169,18 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + return; + } + +- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); ++ new_ccname = krb5_cc_get_name(krb_context, ccache); ++ + client->store.envvar = "KRB5CCNAME"; +- len = strlen(client->store.filename) + 6; +- client->store.envval = xmalloc(len); +- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); ++#ifdef USE_CCAPI ++ xasprintf(&client->store.envval, "API:%s", new_ccname); ++ client->store.filename = NULL; ++#else ++ xasprintf(&client->store.envval, "DIR:%s", new_ccname); ++ if (new_ccname[0] == ':') ++ new_ccname++; ++ client->store.filename = xstrdup(new_ccname); ++#endif + + #ifdef USE_PAM + if (options.use_pam) +@@ -184,6 +192,71 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + return; + } + ++int ++ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, ++ ssh_gssapi_client *client) ++{ ++ krb5_ccache ccache = NULL; ++ krb5_principal principal = NULL; ++ char *name = NULL; ++ krb5_error_code problem; ++ OM_uint32 maj_status, min_status; ++ ++ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { ++ logit("krb5_cc_resolve(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ return 0; ++ } ++ ++ /* Find out who the principal in this cache is */ ++ if ((problem = krb5_cc_get_principal(krb_context, ccache, ++ &principal))) { ++ logit("krb5_cc_get_principal(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ if ((problem = krb5_unparse_name(krb_context, principal, &name))) { ++ logit("krb5_unparse_name(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ ++ if (strcmp(name,client->exportedname.value)!=0) { ++ debug("Name in local credentials cache differs. Not storing"); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ krb5_free_unparsed_name(krb_context, name); ++ return 0; ++ } ++ krb5_free_unparsed_name(krb_context, name); ++ ++ /* Name matches, so lets get on with it! */ ++ ++ if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { ++ logit("krb5_cc_initialize(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ krb5_free_principal(krb_context, principal); ++ ++ if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, ++ ccache))) { ++ logit("gss_krb5_copy_ccache() failed. Sorry!"); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ return 1; ++} ++ + ssh_gssapi_mech gssapi_kerberos_mech = { + "toWM5Slw5Ew8Mqkay+al2g==", + "Kerberos", +@@ -191,7 +264,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { + NULL, + &ssh_gssapi_krb5_userok, + NULL, +- &ssh_gssapi_krb5_storecreds ++ &ssh_gssapi_krb5_storecreds, ++ &ssh_gssapi_krb5_updatecreds + }; + + #endif /* KRB5 */ +diff -up openssh-6.1p1/ChangeLog.gssapi.gsskex openssh-6.1p1/ChangeLog.gssapi +--- openssh-6.1p1/ChangeLog.gssapi.gsskex 2012-09-14 20:57:55.858266892 +0200 ++++ openssh-6.1p1/ChangeLog.gssapi 2012-09-14 20:57:55.859266899 +0200 +@@ -0,0 +1,113 @@ ++20110101 ++ - Finally update for OpenSSH 5.6p1 ++ - Add GSSAPIServerIdentity option from Jim Basney ++ ++20100308 ++ - [ Makefile.in, key.c, key.h ] ++ Updates for OpenSSH 5.4p1 ++ - [ servconf.c ] ++ Include GSSAPI options in the sshd -T configuration dump, and flag ++ some older configuration options as being unsupported. Thanks to Colin ++ Watson. ++ - ++ ++20100124 ++ - [ sshconnect2.c ] ++ Adapt to deal with additional element in Authmethod structure. Thanks to ++ Colin Watson ++ ++20090615 ++ - [ gss-genr.c gss-serv.c kexgssc.c kexgsss.c monitor.c sshconnect2.c ++ sshd.c ] ++ Fix issues identified by Greg Hudson following a code review ++ Check return value of gss_indicate_mechs ++ Protect GSSAPI calls in monitor, so they can only be used if enabled ++ Check return values of bignum functions in key exchange ++ Use BN_clear_free to clear other side's DH value ++ Make ssh_gssapi_id_kex more robust ++ Only configure kex table pointers if GSSAPI is enabled ++ Don't leak mechanism list, or gss mechanism list ++ Cast data.length before printing ++ If serverkey isn't provided, use an empty string, rather than NULL ++ ++20090201 ++ - [ gss-genr.c gss-serv.c kex.h kexgssc.c readconf.c readconf.h ssh-gss.h ++ ssh_config.5 sshconnet2.c ] ++ Add support for the GSSAPIClientIdentity option, which allows the user ++ to specify which GSSAPI identity to use to contact a given server ++ ++20080404 ++ - [ gss-serv.c ] ++ Add code to actually implement GSSAPIStrictAcceptCheck, which had somehow ++ been omitted from a previous version of this patch. Reported by Borislav ++ Stoichkov ++ ++20070317 ++ - [ gss-serv-krb5.c ] ++ Remove C99ism, where new_ccname was being declared in the middle of a ++ function ++ ++20061220 ++ - [ servconf.c ] ++ Make default for GSSAPIStrictAcceptorCheck be Yes, to match previous, and ++ documented, behaviour. Reported by Dan Watson. ++ ++20060910 ++ - [ gss-genr.c kexgssc.c kexgsss.c kex.h monitor.c sshconnect2.c sshd.c ++ ssh-gss.h ] ++ add support for gss-group14-sha1 key exchange mechanisms ++ - [ gss-serv.c servconf.c servconf.h sshd_config sshd_config.5 ] ++ Add GSSAPIStrictAcceptorCheck option to allow the disabling of ++ acceptor principal checking on multi-homed machines. ++ ++ - [ sshd_config ssh_config ] ++ Add settings for GSSAPIKeyExchange and GSSAPITrustDNS to the sample ++ configuration files ++ - [ kexgss.c kegsss.c sshconnect2.c sshd.c ] ++ Code cleanup. Replace strlen/xmalloc/snprintf sequences with xasprintf() ++ Limit length of error messages displayed by client ++ ++20060909 ++ - [ gss-genr.c gss-serv.c ] ++ move ssh_gssapi_acquire_cred() and ssh_gssapi_server_ctx to be server ++ only, where they belong ++ ++ ++20060829 ++ - [ gss-serv-krb5.c ] ++ Fix CCAPI credentials cache name when creating KRB5CCNAME environment ++ variable ++ ++20060828 ++ - [ gss-genr.c ] ++ Avoid Heimdal context freeing problem ++ ++ ++20060818 ++ - [ gss-genr.c ssh-gss.h sshconnect2.c ] ++ Make sure that SPENGO is disabled ++ ++ ++20060421 ++ - [ gssgenr.c, sshconnect2.c ] ++ a few type changes (signed versus unsigned, int versus size_t) to ++ fix compiler errors/warnings ++ (from jbasney AT ncsa.uiuc.edu) ++ - [ kexgssc.c, sshconnect2.c ] ++ fix uninitialized variable warnings ++ (from jbasney AT ncsa.uiuc.edu) ++ - [ gssgenr.c ] ++ pass oid to gss_display_status (helpful when using GSSAPI mechglue) ++ (from jbasney AT ncsa.uiuc.edu) ++ ++ - [ gss-serv-krb5.c ] ++ #ifdef HAVE_GSSAPI_KRB5 should be #ifdef HAVE_GSSAPI_KRB5_H ++ (from jbasney AT ncsa.uiuc.edu) ++ ++ - [ readconf.c, readconf.h, ssh_config.5, sshconnect2.c ++ add client-side GssapiKeyExchange option ++ (from jbasney AT ncsa.uiuc.edu) ++ - [ sshconnect2.c ] ++ add support for GssapiTrustDns option for gssapi-with-mic ++ (from jbasney AT ncsa.uiuc.edu) ++ +diff -up openssh-6.1p1/kex.c.gsskex openssh-6.1p1/kex.c +--- openssh-6.1p1/kex.c.gsskex 2012-09-14 20:57:55.139262298 +0200 ++++ openssh-6.1p1/kex.c 2012-09-14 20:57:55.874266995 +0200 +@@ -51,6 +51,10 @@ + #include "roaming.h" + #include "audit.h" + ++#ifdef GSSAPI ++#include "ssh-gss.h" ++#endif ++ + #if OPENSSL_VERSION_NUMBER >= 0x00907000L + # if defined(HAVE_EVP_SHA256) + # define evp_ssh_sha256 EVP_sha256 +@@ -371,6 +375,20 @@ choose_kex(Kex *k, char *client, char *s + k->kex_type = KEX_ECDH_SHA2; + k->evp_md = kex_ecdh_name_to_evpmd(k->name); + #endif ++#ifdef GSSAPI ++ } else if (strncmp(k->name, KEX_GSS_GEX_SHA1_ID, ++ sizeof(KEX_GSS_GEX_SHA1_ID) - 1) == 0) { ++ k->kex_type = KEX_GSS_GEX_SHA1; ++ k->evp_md = EVP_sha1(); ++ } else if (strncmp(k->name, KEX_GSS_GRP1_SHA1_ID, ++ sizeof(KEX_GSS_GRP1_SHA1_ID) - 1) == 0) { ++ k->kex_type = KEX_GSS_GRP1_SHA1; ++ k->evp_md = EVP_sha1(); ++ } else if (strncmp(k->name, KEX_GSS_GRP14_SHA1_ID, ++ sizeof(KEX_GSS_GRP14_SHA1_ID) - 1) == 0) { ++ k->kex_type = KEX_GSS_GRP14_SHA1; ++ k->evp_md = EVP_sha1(); ++#endif + } else + fatal("bad kex alg %s", k->name); + } +diff -up openssh-6.1p1/kexgssc.c.gsskex openssh-6.1p1/kexgssc.c +--- openssh-6.1p1/kexgssc.c.gsskex 2012-09-14 20:57:55.875267001 +0200 ++++ openssh-6.1p1/kexgssc.c 2012-09-14 20:57:55.875267001 +0200 +@@ -0,0 +1,334 @@ ++/* ++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include "includes.h" ++ ++#ifdef GSSAPI ++ ++#include "includes.h" ++ ++#include ++#include ++ ++#include ++ ++#include "xmalloc.h" ++#include "buffer.h" ++#include "ssh2.h" ++#include "key.h" ++#include "cipher.h" ++#include "kex.h" ++#include "log.h" ++#include "packet.h" ++#include "dh.h" ++ ++#include "ssh-gss.h" ++ ++void ++kexgss_client(Kex *kex) { ++ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; ++ gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr; ++ Gssctxt *ctxt; ++ OM_uint32 maj_status, min_status, ret_flags; ++ u_int klen, kout, slen = 0, hashlen, strlen; ++ DH *dh; ++ BIGNUM *dh_server_pub = NULL; ++ BIGNUM *shared_secret = NULL; ++ BIGNUM *p = NULL; ++ BIGNUM *g = NULL; ++ u_char *kbuf, *hash; ++ u_char *serverhostkey = NULL; ++ u_char *empty = ""; ++ char *msg; ++ char *lang; ++ int type = 0; ++ int first = 1; ++ int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX; ++ ++ /* Initialise our GSSAPI world */ ++ ssh_gssapi_build_ctx(&ctxt); ++ if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) ++ == GSS_C_NO_OID) ++ fatal("Couldn't identify host exchange"); ++ ++ if (ssh_gssapi_import_name(ctxt, kex->gss_host)) ++ fatal("Couldn't import hostname"); ++ ++ if (kex->gss_client && ++ ssh_gssapi_client_identity(ctxt, kex->gss_client)) ++ fatal("Couldn't acquire client credentials"); ++ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ dh = dh_new_group1(); ++ break; ++ case KEX_GSS_GRP14_SHA1: ++ dh = dh_new_group14(); ++ break; ++ case KEX_GSS_GEX_SHA1: ++ debug("Doing group exchange\n"); ++ nbits = dh_estimate(kex->we_need * 8); ++ packet_start(SSH2_MSG_KEXGSS_GROUPREQ); ++ packet_put_int(min); ++ packet_put_int(nbits); ++ packet_put_int(max); ++ ++ packet_send(); ++ ++ packet_read_expect(SSH2_MSG_KEXGSS_GROUP); ++ ++ if ((p = BN_new()) == NULL) ++ fatal("BN_new() failed"); ++ packet_get_bignum2(p); ++ if ((g = BN_new()) == NULL) ++ fatal("BN_new() failed"); ++ packet_get_bignum2(g); ++ packet_check_eom(); ++ ++ if (BN_num_bits(p) < min || BN_num_bits(p) > max) ++ fatal("GSSGRP_GEX group out of range: %d !< %d !< %d", ++ min, BN_num_bits(p), max); ++ ++ dh = dh_new_group(g, p); ++ break; ++ default: ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ } ++ ++ /* Step 1 - e is dh->pub_key */ ++ dh_gen_key(dh, kex->we_need * 8); ++ ++ /* This is f, we initialise it now to make life easier */ ++ dh_server_pub = BN_new(); ++ if (dh_server_pub == NULL) ++ fatal("dh_server_pub == NULL"); ++ ++ token_ptr = GSS_C_NO_BUFFER; ++ ++ do { ++ debug("Calling gss_init_sec_context"); ++ ++ maj_status = ssh_gssapi_init_ctx(ctxt, ++ kex->gss_deleg_creds, token_ptr, &send_tok, ++ &ret_flags); ++ ++ if (GSS_ERROR(maj_status)) { ++ if (send_tok.length != 0) { ++ packet_start(SSH2_MSG_KEXGSS_CONTINUE); ++ packet_put_string(send_tok.value, ++ send_tok.length); ++ } ++ fatal("gss_init_context failed"); ++ } ++ ++ /* If we've got an old receive buffer get rid of it */ ++ if (token_ptr != GSS_C_NO_BUFFER) ++ xfree(recv_tok.value); ++ ++ if (maj_status == GSS_S_COMPLETE) { ++ /* If mutual state flag is not true, kex fails */ ++ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ fatal("Mutual authentication failed"); ++ ++ /* If integ avail flag is not true kex fails */ ++ if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ fatal("Integrity check failed"); ++ } ++ ++ /* ++ * If we have data to send, then the last message that we ++ * received cannot have been a 'complete'. ++ */ ++ if (send_tok.length != 0) { ++ if (first) { ++ packet_start(SSH2_MSG_KEXGSS_INIT); ++ packet_put_string(send_tok.value, ++ send_tok.length); ++ packet_put_bignum2(dh->pub_key); ++ first = 0; ++ } else { ++ packet_start(SSH2_MSG_KEXGSS_CONTINUE); ++ packet_put_string(send_tok.value, ++ send_tok.length); ++ } ++ packet_send(); ++ gss_release_buffer(&min_status, &send_tok); ++ ++ /* If we've sent them data, they should reply */ ++ do { ++ type = packet_read(); ++ if (type == SSH2_MSG_KEXGSS_HOSTKEY) { ++ debug("Received KEXGSS_HOSTKEY"); ++ if (serverhostkey) ++ fatal("Server host key received more than once"); ++ serverhostkey = ++ packet_get_string(&slen); ++ } ++ } while (type == SSH2_MSG_KEXGSS_HOSTKEY); ++ ++ switch (type) { ++ case SSH2_MSG_KEXGSS_CONTINUE: ++ debug("Received GSSAPI_CONTINUE"); ++ if (maj_status == GSS_S_COMPLETE) ++ fatal("GSSAPI Continue received from server when complete"); ++ recv_tok.value = packet_get_string(&strlen); ++ recv_tok.length = strlen; ++ break; ++ case SSH2_MSG_KEXGSS_COMPLETE: ++ debug("Received GSSAPI_COMPLETE"); ++ packet_get_bignum2(dh_server_pub); ++ msg_tok.value = packet_get_string(&strlen); ++ msg_tok.length = strlen; ++ ++ /* Is there a token included? */ ++ if (packet_get_char()) { ++ recv_tok.value= ++ packet_get_string(&strlen); ++ recv_tok.length = strlen; ++ /* If we're already complete - protocol error */ ++ if (maj_status == GSS_S_COMPLETE) ++ packet_disconnect("Protocol error: received token when complete"); ++ } else { ++ /* No token included */ ++ if (maj_status != GSS_S_COMPLETE) ++ packet_disconnect("Protocol error: did not receive final token"); ++ } ++ break; ++ case SSH2_MSG_KEXGSS_ERROR: ++ debug("Received Error"); ++ maj_status = packet_get_int(); ++ min_status = packet_get_int(); ++ msg = packet_get_string(NULL); ++ lang = packet_get_string(NULL); ++ fatal("GSSAPI Error: \n%.400s",msg); ++ default: ++ packet_disconnect("Protocol error: didn't expect packet type %d", ++ type); ++ } ++ token_ptr = &recv_tok; ++ } else { ++ /* No data, and not complete */ ++ if (maj_status != GSS_S_COMPLETE) ++ fatal("Not complete, and no token output"); ++ } ++ } while (maj_status & GSS_S_CONTINUE_NEEDED); ++ ++ /* ++ * We _must_ have received a COMPLETE message in reply from the ++ * server, which will have set dh_server_pub and msg_tok ++ */ ++ ++ if (type != SSH2_MSG_KEXGSS_COMPLETE) ++ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); ++ ++ /* Check f in range [1, p-1] */ ++ if (!dh_pub_is_valid(dh, dh_server_pub)) ++ packet_disconnect("bad server public DH value"); ++ ++ /* compute K=f^x mod p */ ++ klen = DH_size(dh); ++ kbuf = xmalloc(klen); ++ kout = DH_compute_key(kbuf, dh_server_pub, dh); ++ if ((int)kout < 0) ++ fatal("DH_compute_key: failed"); ++ ++ shared_secret = BN_new(); ++ if (shared_secret == NULL) ++ fatal("kexgss_client: BN_new failed"); ++ ++ if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) ++ fatal("kexdh_client: BN_bin2bn failed"); ++ ++ memset(kbuf, 0, klen); ++ xfree(kbuf); ++ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ case KEX_GSS_GRP14_SHA1: ++ kex_dh_hash( kex->client_version_string, ++ kex->server_version_string, ++ buffer_ptr(&kex->my), buffer_len(&kex->my), ++ buffer_ptr(&kex->peer), buffer_len(&kex->peer), ++ (serverhostkey ? serverhostkey : empty), slen, ++ dh->pub_key, /* e */ ++ dh_server_pub, /* f */ ++ shared_secret, /* K */ ++ &hash, &hashlen ++ ); ++ break; ++ case KEX_GSS_GEX_SHA1: ++ kexgex_hash( ++ kex->evp_md, ++ kex->client_version_string, ++ kex->server_version_string, ++ buffer_ptr(&kex->my), buffer_len(&kex->my), ++ buffer_ptr(&kex->peer), buffer_len(&kex->peer), ++ (serverhostkey ? serverhostkey : empty), slen, ++ min, nbits, max, ++ dh->p, dh->g, ++ dh->pub_key, ++ dh_server_pub, ++ shared_secret, ++ &hash, &hashlen ++ ); ++ break; ++ default: ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ } ++ ++ gssbuf.value = hash; ++ gssbuf.length = hashlen; ++ ++ /* Verify that the hash matches the MIC we just got. */ ++ if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) ++ packet_disconnect("Hash's MIC didn't verify"); ++ ++ xfree(msg_tok.value); ++ ++ DH_free(dh); ++ if (serverhostkey) ++ xfree(serverhostkey); ++ BN_clear_free(dh_server_pub); ++ ++ /* save session id */ ++ if (kex->session_id == NULL) { ++ kex->session_id_len = hashlen; ++ kex->session_id = xmalloc(kex->session_id_len); ++ memcpy(kex->session_id, hash, kex->session_id_len); ++ } ++ ++ if (kex->gss_deleg_creds) ++ ssh_gssapi_credentials_updated(ctxt); ++ ++ if (gss_kex_context == NULL) ++ gss_kex_context = ctxt; ++ else ++ ssh_gssapi_delete_ctx(&ctxt); ++ ++ kex_derive_keys(kex, hash, hashlen, shared_secret); ++ BN_clear_free(shared_secret); ++ kex_finish(kex); ++} ++ ++#endif /* GSSAPI */ +diff -up openssh-6.1p1/kexgsss.c.gsskex openssh-6.1p1/kexgsss.c +--- openssh-6.1p1/kexgsss.c.gsskex 2012-09-14 20:57:55.876267007 +0200 ++++ openssh-6.1p1/kexgsss.c 2012-09-14 20:57:55.876267007 +0200 +@@ -0,0 +1,288 @@ ++/* ++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR ++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ */ ++ ++#include "includes.h" ++ ++#ifdef GSSAPI ++ ++#include ++ ++#include ++#include ++ ++#include "xmalloc.h" ++#include "buffer.h" ++#include "ssh2.h" ++#include "key.h" ++#include "cipher.h" ++#include "kex.h" ++#include "log.h" ++#include "packet.h" ++#include "dh.h" ++#include "ssh-gss.h" ++#include "monitor_wrap.h" ++#include "servconf.h" ++ ++extern ServerOptions options; ++ ++void ++kexgss_server(Kex *kex) ++{ ++ OM_uint32 maj_status, min_status; ++ ++ /* ++ * Some GSSAPI implementations use the input value of ret_flags (an ++ * output variable) as a means of triggering mechanism specific ++ * features. Initializing it to zero avoids inadvertently ++ * activating this non-standard behaviour. ++ */ ++ ++ OM_uint32 ret_flags = 0; ++ gss_buffer_desc gssbuf, recv_tok, msg_tok; ++ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; ++ Gssctxt *ctxt = NULL; ++ u_int slen, klen, kout, hashlen; ++ u_char *kbuf, *hash; ++ DH *dh; ++ int min = -1, max = -1, nbits = -1; ++ BIGNUM *shared_secret = NULL; ++ BIGNUM *dh_client_pub = NULL; ++ int type = 0; ++ gss_OID oid; ++ char *mechs; ++ ++ /* Initialise GSSAPI */ ++ ++ /* If we're rekeying, privsep means that some of the private structures ++ * in the GSSAPI code are no longer available. This kludges them back ++ * into life ++ */ ++ if (!ssh_gssapi_oid_table_ok()) ++ if ((mechs = ssh_gssapi_server_mechanisms())) ++ xfree(mechs); ++ ++ debug2("%s: Identifying %s", __func__, kex->name); ++ oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); ++ if (oid == GSS_C_NO_OID) ++ fatal("Unknown gssapi mechanism"); ++ ++ debug2("%s: Acquiring credentials", __func__); ++ ++ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) ++ fatal("Unable to acquire credentials for the server"); ++ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ dh = dh_new_group1(); ++ break; ++ case KEX_GSS_GRP14_SHA1: ++ dh = dh_new_group14(); ++ break; ++ case KEX_GSS_GEX_SHA1: ++ debug("Doing group exchange"); ++ packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ); ++ min = packet_get_int(); ++ nbits = packet_get_int(); ++ max = packet_get_int(); ++ min = MAX(DH_GRP_MIN, min); ++ max = MIN(DH_GRP_MAX, max); ++ packet_check_eom(); ++ if (max < min || nbits < min || max < nbits) ++ fatal("GSS_GEX, bad parameters: %d !< %d !< %d", ++ min, nbits, max); ++ dh = PRIVSEP(choose_dh(min, nbits, max)); ++ if (dh == NULL) ++ packet_disconnect("Protocol error: no matching group found"); ++ ++ packet_start(SSH2_MSG_KEXGSS_GROUP); ++ packet_put_bignum2(dh->p); ++ packet_put_bignum2(dh->g); ++ packet_send(); ++ ++ packet_write_wait(); ++ break; ++ default: ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ } ++ ++ dh_gen_key(dh, kex->we_need * 8); ++ ++ do { ++ debug("Wait SSH2_MSG_GSSAPI_INIT"); ++ type = packet_read(); ++ switch(type) { ++ case SSH2_MSG_KEXGSS_INIT: ++ if (dh_client_pub != NULL) ++ fatal("Received KEXGSS_INIT after initialising"); ++ recv_tok.value = packet_get_string(&slen); ++ recv_tok.length = slen; ++ ++ if ((dh_client_pub = BN_new()) == NULL) ++ fatal("dh_client_pub == NULL"); ++ ++ packet_get_bignum2(dh_client_pub); ++ ++ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ ++ break; ++ case SSH2_MSG_KEXGSS_CONTINUE: ++ recv_tok.value = packet_get_string(&slen); ++ recv_tok.length = slen; ++ break; ++ default: ++ packet_disconnect( ++ "Protocol error: didn't expect packet type %d", ++ type); ++ } ++ ++ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, ++ &send_tok, &ret_flags)); ++ ++ xfree(recv_tok.value); ++ ++ if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) ++ fatal("Zero length token output when incomplete"); ++ ++ if (dh_client_pub == NULL) ++ fatal("No client public key"); ++ ++ if (maj_status & GSS_S_CONTINUE_NEEDED) { ++ debug("Sending GSSAPI_CONTINUE"); ++ packet_start(SSH2_MSG_KEXGSS_CONTINUE); ++ packet_put_string(send_tok.value, send_tok.length); ++ packet_send(); ++ gss_release_buffer(&min_status, &send_tok); ++ } ++ } while (maj_status & GSS_S_CONTINUE_NEEDED); ++ ++ if (GSS_ERROR(maj_status)) { ++ if (send_tok.length > 0) { ++ packet_start(SSH2_MSG_KEXGSS_CONTINUE); ++ packet_put_string(send_tok.value, send_tok.length); ++ packet_send(); ++ } ++ fatal("accept_ctx died"); ++ } ++ ++ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ fatal("Mutual Authentication flag wasn't set"); ++ ++ if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ fatal("Integrity flag wasn't set"); ++ ++ if (!dh_pub_is_valid(dh, dh_client_pub)) ++ packet_disconnect("bad client public DH value"); ++ ++ klen = DH_size(dh); ++ kbuf = xmalloc(klen); ++ kout = DH_compute_key(kbuf, dh_client_pub, dh); ++ if ((int)kout < 0) ++ fatal("DH_compute_key: failed"); ++ ++ shared_secret = BN_new(); ++ if (shared_secret == NULL) ++ fatal("kexgss_server: BN_new failed"); ++ ++ if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) ++ fatal("kexgss_server: BN_bin2bn failed"); ++ ++ memset(kbuf, 0, klen); ++ xfree(kbuf); ++ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ case KEX_GSS_GRP14_SHA1: ++ kex_dh_hash( ++ kex->client_version_string, kex->server_version_string, ++ buffer_ptr(&kex->peer), buffer_len(&kex->peer), ++ buffer_ptr(&kex->my), buffer_len(&kex->my), ++ NULL, 0, /* Change this if we start sending host keys */ ++ dh_client_pub, dh->pub_key, shared_secret, ++ &hash, &hashlen ++ ); ++ break; ++ case KEX_GSS_GEX_SHA1: ++ kexgex_hash( ++ kex->evp_md, ++ kex->client_version_string, kex->server_version_string, ++ buffer_ptr(&kex->peer), buffer_len(&kex->peer), ++ buffer_ptr(&kex->my), buffer_len(&kex->my), ++ NULL, 0, ++ min, nbits, max, ++ dh->p, dh->g, ++ dh_client_pub, ++ dh->pub_key, ++ shared_secret, ++ &hash, &hashlen ++ ); ++ break; ++ default: ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ } ++ ++ BN_clear_free(dh_client_pub); ++ ++ if (kex->session_id == NULL) { ++ kex->session_id_len = hashlen; ++ kex->session_id = xmalloc(kex->session_id_len); ++ memcpy(kex->session_id, hash, kex->session_id_len); ++ } ++ ++ gssbuf.value = hash; ++ gssbuf.length = hashlen; ++ ++ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok)))) ++ fatal("Couldn't get MIC"); ++ ++ packet_start(SSH2_MSG_KEXGSS_COMPLETE); ++ packet_put_bignum2(dh->pub_key); ++ packet_put_string(msg_tok.value,msg_tok.length); ++ ++ if (send_tok.length != 0) { ++ packet_put_char(1); /* true */ ++ packet_put_string(send_tok.value, send_tok.length); ++ } else { ++ packet_put_char(0); /* false */ ++ } ++ packet_send(); ++ ++ gss_release_buffer(&min_status, &send_tok); ++ gss_release_buffer(&min_status, &msg_tok); ++ ++ if (gss_kex_context == NULL) ++ gss_kex_context = ctxt; ++ else ++ ssh_gssapi_delete_ctx(&ctxt); ++ ++ DH_free(dh); ++ ++ kex_derive_keys(kex, hash, hashlen, shared_secret); ++ BN_clear_free(shared_secret); ++ kex_finish(kex); ++ ++ /* If this was a rekey, then save out any delegated credentials we ++ * just exchanged. */ ++ if (options.gss_store_rekey) ++ ssh_gssapi_rekey_creds(); ++} ++#endif /* GSSAPI */ +diff -up openssh-6.1p1/kex.h.gsskex openssh-6.1p1/kex.h +--- openssh-6.1p1/kex.h.gsskex 2012-09-14 20:57:55.141262312 +0200 ++++ openssh-6.1p1/kex.h 2012-09-14 20:57:55.878267019 +0200 +@@ -73,6 +73,9 @@ enum kex_exchange { + KEX_DH_GEX_SHA1, + KEX_DH_GEX_SHA256, + KEX_ECDH_SHA2, ++ KEX_GSS_GRP1_SHA1, ++ KEX_GSS_GRP14_SHA1, ++ KEX_GSS_GEX_SHA1, + KEX_MAX + }; + +@@ -129,6 +132,12 @@ struct Kex { + sig_atomic_t done; + int flags; + const EVP_MD *evp_md; ++#ifdef GSSAPI ++ int gss_deleg_creds; ++ int gss_trust_dns; ++ char *gss_host; ++ char *gss_client; ++#endif + char *client_version_string; + char *server_version_string; + int (*verify_host_key)(Key *); +@@ -156,6 +165,11 @@ void kexgex_server(Kex *); + void kexecdh_client(Kex *); + void kexecdh_server(Kex *); + ++#ifdef GSSAPI ++void kexgss_client(Kex *); ++void kexgss_server(Kex *); ++#endif ++ + void newkeys_destroy(Newkeys *newkeys); + + void +diff -up openssh-6.1p1/key.c.gsskex openssh-6.1p1/key.c +--- openssh-6.1p1/key.c.gsskex 2012-09-14 20:57:55.593265199 +0200 ++++ openssh-6.1p1/key.c 2012-09-14 20:57:55.881267039 +0200 +@@ -1011,6 +1011,8 @@ key_ssh_name_from_type_nid(int type, int + } + break; + #endif /* OPENSSL_HAS_ECC */ ++ case KEY_NULL: ++ return "null"; + } + return "ssh-unknown"; + } +@@ -1316,6 +1318,8 @@ key_type_from_name(char *name) + strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) { + return KEY_ECDSA_CERT; + #endif ++ } else if (strcmp(name, "null") == 0) { ++ return KEY_NULL; + } + + debug2("key_type_from_name: unknown key type '%s'", name); +diff -up openssh-6.1p1/key.h.gsskex openssh-6.1p1/key.h +--- openssh-6.1p1/key.h.gsskex 2012-09-14 20:57:55.184262586 +0200 ++++ openssh-6.1p1/key.h 2012-09-14 20:57:55.882267045 +0200 +@@ -44,6 +44,7 @@ enum types { + KEY_ECDSA_CERT, + KEY_RSA_CERT_V00, + KEY_DSA_CERT_V00, ++ KEY_NULL, + KEY_UNSPEC + }; + enum fp_type { +diff -up openssh-6.1p1/Makefile.in.gsskex openssh-6.1p1/Makefile.in +--- openssh-6.1p1/Makefile.in.gsskex 2012-09-14 20:57:55.832266726 +0200 ++++ openssh-6.1p1/Makefile.in 2012-09-14 20:57:55.884267058 +0200 +@@ -75,6 +75,7 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o b + atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \ + monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ + kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ ++ kexgssc.o \ + msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o jpake.o \ + schnorr.o ssh-pkcs11.o auditstub.o + +@@ -91,7 +92,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw + auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \ + monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \ + auth-krb5.o \ +- auth2-gss.o gss-serv.o gss-serv-krb5.o \ ++ auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o\ + loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \ + sftp-server.o sftp-common.o \ + roaming_common.o roaming_serv.o \ +diff -up openssh-6.1p1/monitor.c.gsskex openssh-6.1p1/monitor.c +--- openssh-6.1p1/monitor.c.gsskex 2012-09-14 20:57:55.299263321 +0200 ++++ openssh-6.1p1/monitor.c 2012-09-14 20:57:55.888267083 +0200 +@@ -186,6 +186,8 @@ int mm_answer_gss_setup_ctx(int, Buffer + int mm_answer_gss_accept_ctx(int, Buffer *); + int mm_answer_gss_userok(int, Buffer *); + int mm_answer_gss_checkmic(int, Buffer *); ++int mm_answer_gss_sign(int, Buffer *); ++int mm_answer_gss_updatecreds(int, Buffer *); + #endif + + #ifdef SSH_AUDIT_EVENTS +@@ -270,6 +272,7 @@ struct mon_table mon_dispatch_proto20[] + {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, + {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, + {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, ++ {MONITOR_REQ_GSSSIGN, MON_ONCE, mm_answer_gss_sign}, + #endif + #ifdef JPAKE + {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata}, +@@ -282,6 +285,12 @@ struct mon_table mon_dispatch_proto20[] + }; + + struct mon_table mon_dispatch_postauth20[] = { ++#ifdef GSSAPI ++ {MONITOR_REQ_GSSSETUP, 0, mm_answer_gss_setup_ctx}, ++ {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, ++ {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, ++ {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, ++#endif + {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, + {MONITOR_REQ_SIGN, 0, mm_answer_sign}, + {MONITOR_REQ_PTY, 0, mm_answer_pty}, +@@ -406,6 +415,10 @@ monitor_child_preauth(Authctxt *_authctx + /* Permit requests for moduli and signatures */ + monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); ++#ifdef GSSAPI ++ /* and for the GSSAPI key exchange */ ++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); ++#endif + } else { + mon_dispatch = mon_dispatch_proto15; + req_auth = &options.required_auth1; +@@ -512,6 +525,10 @@ monitor_child_postauth(struct monitor *p + monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); ++#ifdef GSSAPI ++ /* and for the GSSAPI key exchange */ ++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); ++#endif + } else { + mon_dispatch = mon_dispatch_postauth15; + monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); +@@ -1939,6 +1956,13 @@ mm_get_kex(Buffer *m) + kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; + kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; + kex->kex[KEX_ECDH_SHA2] = kexecdh_server; ++#ifdef GSSAPI ++ if (options.gss_keyex) { ++ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; ++ } ++#endif + kex->server = 1; + kex->hostkey_type = buffer_get_int(m); + kex->kex_type = buffer_get_int(m); +@@ -2162,6 +2186,9 @@ mm_answer_gss_setup_ctx(int sock, Buffer + OM_uint32 major; + u_int len; + ++ if (!options.gss_authentication && !options.gss_keyex) ++ fatal("In GSSAPI monitor when GSSAPI is disabled"); ++ + goid.elements = buffer_get_string(m, &len); + goid.length = len; + +@@ -2189,6 +2216,9 @@ mm_answer_gss_accept_ctx(int sock, Buffe + OM_uint32 flags = 0; /* GSI needs this */ + u_int len; + ++ if (!options.gss_authentication && !options.gss_keyex) ++ fatal("In GSSAPI monitor when GSSAPI is disabled"); ++ + in.value = buffer_get_string(m, &len); + in.length = len; + major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); +@@ -2206,6 +2236,7 @@ mm_answer_gss_accept_ctx(int sock, Buffe + monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); ++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSIGN, 1); + } + return (0); + } +@@ -2217,6 +2248,9 @@ mm_answer_gss_checkmic(int sock, Buffer + OM_uint32 ret; + u_int len; + ++ if (!options.gss_authentication && !options.gss_keyex) ++ fatal("In GSSAPI monitor when GSSAPI is disabled"); ++ + gssbuf.value = buffer_get_string(m, &len); + gssbuf.length = len; + mic.value = buffer_get_string(m, &len); +@@ -2243,7 +2277,11 @@ mm_answer_gss_userok(int sock, Buffer *m + { + int authenticated; + +- authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); ++ if (!options.gss_authentication && !options.gss_keyex) ++ fatal("In GSSAPI monitor when GSSAPI is disabled"); ++ ++ authenticated = authctxt->valid && ++ ssh_gssapi_userok(authctxt->user, authctxt->pw); + + buffer_clear(m); + buffer_put_int(m, authenticated); +@@ -2257,6 +2295,74 @@ mm_answer_gss_userok(int sock, Buffer *m + /* Monitor loop will terminate if authenticated */ + return (authenticated); + } ++ ++int ++mm_answer_gss_sign(int socket, Buffer *m) ++{ ++ gss_buffer_desc data; ++ gss_buffer_desc hash = GSS_C_EMPTY_BUFFER; ++ OM_uint32 major, minor; ++ u_int len; ++ ++ if (!options.gss_authentication && !options.gss_keyex) ++ fatal("In GSSAPI monitor when GSSAPI is disabled"); ++ ++ data.value = buffer_get_string(m, &len); ++ data.length = len; ++ if (data.length != 20) ++ fatal("%s: data length incorrect: %d", __func__, ++ (int) data.length); ++ ++ /* Save the session ID on the first time around */ ++ if (session_id2_len == 0) { ++ session_id2_len = data.length; ++ session_id2 = xmalloc(session_id2_len); ++ memcpy(session_id2, data.value, session_id2_len); ++ } ++ major = ssh_gssapi_sign(gsscontext, &data, &hash); ++ ++ xfree(data.value); ++ ++ buffer_clear(m); ++ buffer_put_int(m, major); ++ buffer_put_string(m, hash.value, hash.length); ++ ++ mm_request_send(socket, MONITOR_ANS_GSSSIGN, m); ++ ++ gss_release_buffer(&minor, &hash); ++ ++ /* Turn on getpwnam permissions */ ++ monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); ++ ++ /* And credential updating, for when rekeying */ ++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1); ++ ++ return (0); ++} ++ ++int ++mm_answer_gss_updatecreds(int socket, Buffer *m) { ++ ssh_gssapi_ccache store; ++ int ok; ++ ++ store.filename = buffer_get_string(m, NULL); ++ store.envvar = buffer_get_string(m, NULL); ++ store.envval = buffer_get_string(m, NULL); ++ ++ ok = ssh_gssapi_update_creds(&store); ++ ++ xfree(store.filename); ++ xfree(store.envvar); ++ xfree(store.envval); ++ ++ buffer_clear(m); ++ buffer_put_int(m, ok); ++ ++ mm_request_send(socket, MONITOR_ANS_GSSUPCREDS, m); ++ ++ return(0); ++} ++ + #endif /* GSSAPI */ + + #ifdef JPAKE +diff -up openssh-6.1p1/monitor.h.gsskex openssh-6.1p1/monitor.h +--- openssh-6.1p1/monitor.h.gsskex 2012-09-14 20:57:55.300263327 +0200 ++++ openssh-6.1p1/monitor.h 2012-09-14 20:57:55.889267090 +0200 +@@ -56,6 +56,8 @@ enum monitor_reqtype { + MONITOR_REQ_GSSSTEP, MONITOR_ANS_GSSSTEP, + MONITOR_REQ_GSSUSEROK, MONITOR_ANS_GSSUSEROK, + MONITOR_REQ_GSSCHECKMIC, MONITOR_ANS_GSSCHECKMIC, ++ MONITOR_REQ_GSSSIGN, MONITOR_ANS_GSSSIGN, ++ MONITOR_REQ_GSSUPCREDS, MONITOR_ANS_GSSUPCREDS, + MONITOR_REQ_PAM_START, + MONITOR_REQ_PAM_ACCOUNT, MONITOR_ANS_PAM_ACCOUNT, + MONITOR_REQ_PAM_INIT_CTX, MONITOR_ANS_PAM_INIT_CTX, +diff -up openssh-6.1p1/monitor_wrap.c.gsskex openssh-6.1p1/monitor_wrap.c +--- openssh-6.1p1/monitor_wrap.c.gsskex 2012-09-14 20:57:55.302263340 +0200 ++++ openssh-6.1p1/monitor_wrap.c 2012-09-14 20:57:55.892267109 +0200 +@@ -1326,7 +1326,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss + } + + int +-mm_ssh_gssapi_userok(char *user) ++mm_ssh_gssapi_userok(char *user, struct passwd *pw) + { + Buffer m; + int authenticated = 0; +@@ -1343,6 +1343,51 @@ mm_ssh_gssapi_userok(char *user) + debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); + return (authenticated); + } ++ ++OM_uint32 ++mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) ++{ ++ Buffer m; ++ OM_uint32 major; ++ u_int len; ++ ++ buffer_init(&m); ++ buffer_put_string(&m, data->value, data->length); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m); ++ ++ major = buffer_get_int(&m); ++ hash->value = buffer_get_string(&m, &len); ++ hash->length = len; ++ ++ buffer_free(&m); ++ ++ return(major); ++} ++ ++int ++mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store) ++{ ++ Buffer m; ++ int ok; ++ ++ buffer_init(&m); ++ ++ buffer_put_cstring(&m, store->filename ? store->filename : ""); ++ buffer_put_cstring(&m, store->envvar ? store->envvar : ""); ++ buffer_put_cstring(&m, store->envval ? store->envval : ""); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, &m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUPCREDS, &m); ++ ++ ok = buffer_get_int(&m); ++ ++ buffer_free(&m); ++ ++ return (ok); ++} ++ + #endif /* GSSAPI */ + + #ifdef JPAKE +diff -up openssh-6.1p1/monitor_wrap.h.gsskex openssh-6.1p1/monitor_wrap.h +--- openssh-6.1p1/monitor_wrap.h.gsskex 2012-09-14 20:57:55.304263353 +0200 ++++ openssh-6.1p1/monitor_wrap.h 2012-09-14 20:57:55.893267116 +0200 +@@ -62,8 +62,10 @@ BIGNUM *mm_auth_rsa_generate_challenge(K + OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); + OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *, + gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); +-int mm_ssh_gssapi_userok(char *user); ++int mm_ssh_gssapi_userok(char *user, struct passwd *); + OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); ++OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); ++int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *); + #endif + + #ifdef USE_PAM +diff -up openssh-6.1p1/readconf.c.gsskex openssh-6.1p1/readconf.c +--- openssh-6.1p1/readconf.c.gsskex 2011-10-02 09:59:03.000000000 +0200 ++++ openssh-6.1p1/readconf.c 2012-09-14 20:57:55.896267134 +0200 +@@ -129,6 +129,8 @@ typedef enum { + oClearAllForwardings, oNoHostAuthenticationForLocalhost, + oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, + oAddressFamily, oGssAuthentication, oGssDelegateCreds, ++ oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey, ++ oGssServerIdentity, + oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, + oSendEnv, oControlPath, oControlMaster, oControlPersist, + oHashKnownHosts, +@@ -169,10 +171,19 @@ static struct { + { "afstokenpassing", oUnsupported }, + #if defined(GSSAPI) + { "gssapiauthentication", oGssAuthentication }, ++ { "gssapikeyexchange", oGssKeyEx }, + { "gssapidelegatecredentials", oGssDelegateCreds }, ++ { "gssapitrustdns", oGssTrustDns }, ++ { "gssapiclientidentity", oGssClientIdentity }, ++ { "gssapiserveridentity", oGssServerIdentity }, ++ { "gssapirenewalforcesrekey", oGssRenewalRekey }, + #else + { "gssapiauthentication", oUnsupported }, ++ { "gssapikeyexchange", oUnsupported }, + { "gssapidelegatecredentials", oUnsupported }, ++ { "gssapitrustdns", oUnsupported }, ++ { "gssapiclientidentity", oUnsupported }, ++ { "gssapirenewalforcesrekey", oUnsupported }, + #endif + { "fallbacktorsh", oDeprecated }, + { "usersh", oDeprecated }, +@@ -483,10 +494,30 @@ parse_flag: + intptr = &options->gss_authentication; + goto parse_flag; + ++ case oGssKeyEx: ++ intptr = &options->gss_keyex; ++ goto parse_flag; ++ + case oGssDelegateCreds: + intptr = &options->gss_deleg_creds; + goto parse_flag; + ++ case oGssTrustDns: ++ intptr = &options->gss_trust_dns; ++ goto parse_flag; ++ ++ case oGssClientIdentity: ++ charptr = &options->gss_client_identity; ++ goto parse_string; ++ ++ case oGssServerIdentity: ++ charptr = &options->gss_server_identity; ++ goto parse_string; ++ ++ case oGssRenewalRekey: ++ intptr = &options->gss_renewal_rekey; ++ goto parse_flag; ++ + case oBatchMode: + intptr = &options->batch_mode; + goto parse_flag; +@@ -1139,7 +1170,12 @@ initialize_options(Options * options) + options->pubkey_authentication = -1; + options->challenge_response_authentication = -1; + options->gss_authentication = -1; ++ options->gss_keyex = -1; + options->gss_deleg_creds = -1; ++ options->gss_trust_dns = -1; ++ options->gss_renewal_rekey = -1; ++ options->gss_client_identity = NULL; ++ options->gss_server_identity = NULL; + options->password_authentication = -1; + options->kbd_interactive_authentication = -1; + options->kbd_interactive_devices = NULL; +@@ -1239,8 +1275,14 @@ fill_default_options(Options * options) + options->challenge_response_authentication = 1; + if (options->gss_authentication == -1) + options->gss_authentication = 0; ++ if (options->gss_keyex == -1) ++ options->gss_keyex = 0; + if (options->gss_deleg_creds == -1) + options->gss_deleg_creds = 0; ++ if (options->gss_trust_dns == -1) ++ options->gss_trust_dns = 0; ++ if (options->gss_renewal_rekey == -1) ++ options->gss_renewal_rekey = 0; + if (options->password_authentication == -1) + options->password_authentication = 1; + if (options->kbd_interactive_authentication == -1) +diff -up openssh-6.1p1/readconf.h.gsskex openssh-6.1p1/readconf.h +--- openssh-6.1p1/readconf.h.gsskex 2011-10-02 09:59:03.000000000 +0200 ++++ openssh-6.1p1/readconf.h 2012-09-14 20:57:55.897267141 +0200 +@@ -48,7 +48,12 @@ typedef struct { + int challenge_response_authentication; + /* Try S/Key or TIS, authentication. */ + int gss_authentication; /* Try GSS authentication */ ++ int gss_keyex; /* Try GSS key exchange */ + int gss_deleg_creds; /* Delegate GSS credentials */ ++ int gss_trust_dns; /* Trust DNS for GSS canonicalization */ ++ int gss_renewal_rekey; /* Credential renewal forces rekey */ ++ char *gss_client_identity; /* Principal to initiate GSSAPI with */ ++ char *gss_server_identity; /* GSSAPI target principal */ + int password_authentication; /* Try password + * authentication. */ + int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ +diff -up openssh-6.1p1/servconf.c.gsskex openssh-6.1p1/servconf.c +--- openssh-6.1p1/servconf.c.gsskex 2012-09-14 20:57:55.760266266 +0200 ++++ openssh-6.1p1/servconf.c 2012-09-14 20:57:55.900267160 +0200 +@@ -102,7 +102,10 @@ initialize_server_options(ServerOptions + options->kerberos_ticket_cleanup = -1; + options->kerberos_get_afs_token = -1; + options->gss_authentication=-1; ++ options->gss_keyex = -1; + options->gss_cleanup_creds = -1; ++ options->gss_strict_acceptor = -1; ++ options->gss_store_rekey = -1; + options->password_authentication = -1; + options->kbd_interactive_authentication = -1; + options->challenge_response_authentication = -1; +@@ -236,8 +239,14 @@ fill_default_server_options(ServerOption + options->kerberos_get_afs_token = 0; + if (options->gss_authentication == -1) + options->gss_authentication = 0; ++ if (options->gss_keyex == -1) ++ options->gss_keyex = 0; + if (options->gss_cleanup_creds == -1) + options->gss_cleanup_creds = 1; ++ if (options->gss_strict_acceptor == -1) ++ options->gss_strict_acceptor = 1; ++ if (options->gss_store_rekey == -1) ++ options->gss_store_rekey = 0; + if (options->password_authentication == -1) + options->password_authentication = 1; + if (options->kbd_interactive_authentication == -1) +@@ -333,7 +342,9 @@ typedef enum { + sBanner, sShowPatchLevel, sUseDNS, sHostbasedAuthentication, + sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, + sClientAliveCountMax, sAuthorizedKeysFile, +- sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, ++ sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, ++ sGssKeyEx, sGssStoreRekey, ++ sAcceptEnv, sPermitTunnel, + sRequiredAuthentications1, sRequiredAuthentications2, + sMatch, sPermitOpen, sForceCommand, sChrootDirectory, + sUsePrivilegeSeparation, sAllowAgentForwarding, +@@ -399,10 +410,20 @@ static struct { + #ifdef GSSAPI + { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, + { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, ++ { "gssapicleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL }, ++ { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, ++ { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, ++ { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, + #else + { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, + { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, + #endif ++ { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL }, + { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, + { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, + { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, +@@ -1054,10 +1075,22 @@ process_server_config_line(ServerOptions + intptr = &options->gss_authentication; + goto parse_flag; + ++ case sGssKeyEx: ++ intptr = &options->gss_keyex; ++ goto parse_flag; ++ + case sGssCleanupCreds: + intptr = &options->gss_cleanup_creds; + goto parse_flag; + ++ case sGssStrictAcceptor: ++ intptr = &options->gss_strict_acceptor; ++ goto parse_flag; ++ ++ case sGssStoreRekey: ++ intptr = &options->gss_store_rekey; ++ goto parse_flag; ++ + case sPasswordAuthentication: + intptr = &options->password_authentication; + goto parse_flag; +@@ -1944,6 +1977,9 @@ dump_config(ServerOptions *o) + #ifdef GSSAPI + dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); + dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); ++ dump_cfg_fmtint(sGssKeyEx, o->gss_keyex); ++ dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor); ++ dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey); + #endif + #ifdef JPAKE + dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication, +diff -up openssh-6.1p1/servconf.h.gsskex openssh-6.1p1/servconf.h +--- openssh-6.1p1/servconf.h.gsskex 2012-09-14 20:57:55.762266278 +0200 ++++ openssh-6.1p1/servconf.h 2012-09-14 20:57:55.902267173 +0200 +@@ -103,7 +103,10 @@ typedef struct { + int kerberos_get_afs_token; /* If true, try to get AFS token if + * authenticated with Kerberos. */ + int gss_authentication; /* If true, permit GSSAPI authentication */ ++ int gss_keyex; /* If true, permit GSSAPI key exchange */ + int gss_cleanup_creds; /* If true, destroy cred cache on logout */ ++ int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */ ++ int gss_store_rekey; + int password_authentication; /* If true, permit password + * authentication. */ + int kbd_interactive_authentication; /* If true, permit */ +diff -up openssh-6.1p1/ssh_config.gsskex openssh-6.1p1/ssh_config +--- openssh-6.1p1/ssh_config.gsskex 2012-09-14 20:57:55.707265928 +0200 ++++ openssh-6.1p1/ssh_config 2012-09-14 20:57:55.906267198 +0200 +@@ -26,6 +26,8 @@ + # HostbasedAuthentication no + # GSSAPIAuthentication no + # GSSAPIDelegateCredentials no ++# GSSAPIKeyExchange no ++# GSSAPITrustDNS no + # BatchMode no + # CheckHostIP yes + # AddressFamily any +diff -up openssh-6.1p1/ssh_config.5.gsskex openssh-6.1p1/ssh_config.5 +--- openssh-6.1p1/ssh_config.5.gsskex 2012-07-02 10:53:38.000000000 +0200 ++++ openssh-6.1p1/ssh_config.5 2012-09-14 20:57:55.904267186 +0200 +@@ -527,11 +527,43 @@ Specifies whether user authentication ba + The default is + .Dq no . + Note that this option applies to protocol version 2 only. ++.It Cm GSSAPIKeyExchange ++Specifies whether key exchange based on GSSAPI may be used. When using ++GSSAPI key exchange the server need not have a host key. ++The default is ++.Dq no . ++Note that this option applies to protocol version 2 only. ++.It Cm GSSAPIClientIdentity ++If set, specifies the GSSAPI client identity that ssh should use when ++connecting to the server. The default is unset, which means that the default ++identity will be used. ++.It Cm GSSAPIServerIdentity ++If set, specifies the GSSAPI server identity that ssh should expect when ++connecting to the server. The default is unset, which means that the ++expected GSSAPI server identity will be determined from the target ++hostname. + .It Cm GSSAPIDelegateCredentials + Forward (delegate) credentials to the server. + The default is + .Dq no . +-Note that this option applies to protocol version 2 only. ++Note that this option applies to protocol version 2 connections using GSSAPI. ++.It Cm GSSAPIRenewalForcesRekey ++If set to ++.Dq yes ++then renewal of the client's GSSAPI credentials will force the rekeying of the ++ssh connection. With a compatible server, this can delegate the renewed ++credentials to a session on the server. ++The default is ++.Dq no . ++.It Cm GSSAPITrustDns ++Set to ++.Dq yes to indicate that the DNS is trusted to securely canonicalize ++the name of the host being connected to. If ++.Dq no, the hostname entered on the ++command line will be passed untouched to the GSSAPI library. ++The default is ++.Dq no . ++This option only applies to protocol version 2 connections using GSSAPI. + .It Cm HashKnownHosts + Indicates that + .Xr ssh 1 +diff -up openssh-6.1p1/sshconnect2.c.gsskex openssh-6.1p1/sshconnect2.c +--- openssh-6.1p1/sshconnect2.c.gsskex 2012-09-14 20:57:55.605265275 +0200 ++++ openssh-6.1p1/sshconnect2.c 2012-09-14 20:57:55.909267218 +0200 +@@ -162,9 +162,34 @@ ssh_kex2(char *host, struct sockaddr *ho + { + Kex *kex; + ++#ifdef GSSAPI ++ char *orig = NULL, *gss = NULL; ++ char *gss_host = NULL; ++#endif ++ + xxx_host = host; + xxx_hostaddr = hostaddr; + ++#ifdef GSSAPI ++ if (options.gss_keyex) { ++ /* Add the GSSAPI mechanisms currently supported on this ++ * client to the key exchange algorithm proposal */ ++ orig = myproposal[PROPOSAL_KEX_ALGS]; ++ ++ if (options.gss_trust_dns) ++ gss_host = (char *)get_canonical_hostname(1); ++ else ++ gss_host = host; ++ ++ gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity); ++ if (gss) { ++ debug("Offering GSSAPI proposal: %s", gss); ++ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], ++ "%s,%s", gss, orig); ++ } ++ } ++#endif ++ + if (options.ciphers == (char *)-1) { + logit("No valid ciphers for protocol version 2 given, using defaults."); + options.ciphers = NULL; +@@ -207,6 +232,17 @@ ssh_kex2(char *host, struct sockaddr *ho + if (options.kex_algorithms != NULL) + myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; + ++#ifdef GSSAPI ++ /* If we've got GSSAPI algorithms, then we also support the ++ * 'null' hostkey, as a last resort */ ++ if (options.gss_keyex && gss) { ++ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; ++ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], ++ "%s,null", orig); ++ xfree(gss); ++ } ++#endif ++ + if (options.rekey_limit) + packet_set_rekey_limit((u_int32_t)options.rekey_limit); + +@@ -217,10 +253,30 @@ ssh_kex2(char *host, struct sockaddr *ho + kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; + kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; + kex->kex[KEX_ECDH_SHA2] = kexecdh_client; ++#ifdef GSSAPI ++ if (options.gss_keyex) { ++ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; ++ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client; ++ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; ++ } ++#endif + kex->client_version_string=client_version_string; + kex->server_version_string=server_version_string; + kex->verify_host_key=&verify_host_key_callback; + ++#ifdef GSSAPI ++ if (options.gss_keyex) { ++ kex->gss_deleg_creds = options.gss_deleg_creds; ++ kex->gss_trust_dns = options.gss_trust_dns; ++ kex->gss_client = options.gss_client_identity; ++ if (options.gss_server_identity) { ++ kex->gss_host = options.gss_server_identity; ++ } else { ++ kex->gss_host = gss_host; ++ } ++ } ++#endif ++ + xxx_kex = kex; + + dispatch_run(DISPATCH_BLOCK, &kex->done, kex); +@@ -315,6 +371,7 @@ void input_gssapi_token(int type, u_int3 + void input_gssapi_hash(int type, u_int32_t, void *); + void input_gssapi_error(int, u_int32_t, void *); + void input_gssapi_errtok(int, u_int32_t, void *); ++int userauth_gsskeyex(Authctxt *authctxt); + #endif + + void userauth(Authctxt *, char *); +@@ -330,6 +387,11 @@ static char *authmethods_get(void); + + Authmethod authmethods[] = { + #ifdef GSSAPI ++ {"gssapi-keyex", ++ userauth_gsskeyex, ++ NULL, ++ &options.gss_authentication, ++ NULL}, + {"gssapi-with-mic", + userauth_gssapi, + NULL, +@@ -637,19 +699,31 @@ userauth_gssapi(Authctxt *authctxt) + static u_int mech = 0; + OM_uint32 min; + int ok = 0; ++ const char *gss_host; ++ ++ if (options.gss_server_identity) ++ gss_host = options.gss_server_identity; ++ else if (options.gss_trust_dns) ++ gss_host = get_canonical_hostname(1); ++ else ++ gss_host = authctxt->host; + + /* Try one GSSAPI method at a time, rather than sending them all at + * once. */ + + if (gss_supported == NULL) +- gss_indicate_mechs(&min, &gss_supported); ++ if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) { ++ gss_supported = NULL; ++ return 0; ++ } + + /* Check to see if the mechanism is usable before we offer it */ + while (mech < gss_supported->count && !ok) { + /* My DER encoding requires length<128 */ + if (gss_supported->elements[mech].length < 128 && + ssh_gssapi_check_mechanism(&gssctxt, +- &gss_supported->elements[mech], authctxt->host)) { ++ &gss_supported->elements[mech], gss_host, ++ options.gss_client_identity)) { + ok = 1; /* Mechanism works */ + } else { + mech++; +@@ -746,8 +820,8 @@ input_gssapi_response(int type, u_int32_ + { + Authctxt *authctxt = ctxt; + Gssctxt *gssctxt; +- int oidlen; +- char *oidv; ++ u_int oidlen; ++ u_char *oidv; + + if (authctxt == NULL) + fatal("input_gssapi_response: no authentication context"); +@@ -857,6 +931,48 @@ input_gssapi_error(int type, u_int32_t p + xfree(msg); + xfree(lang); + } ++ ++int ++userauth_gsskeyex(Authctxt *authctxt) ++{ ++ Buffer b; ++ gss_buffer_desc gssbuf; ++ gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ms; ++ ++ static int attempt = 0; ++ if (attempt++ >= 1) ++ return (0); ++ ++ if (gss_kex_context == NULL) { ++ debug("No valid Key exchange context"); ++ return (0); ++ } ++ ++ ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service, ++ "gssapi-keyex"); ++ ++ gssbuf.value = buffer_ptr(&b); ++ gssbuf.length = buffer_len(&b); ++ ++ if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) { ++ buffer_free(&b); ++ return (0); ++ } ++ ++ packet_start(SSH2_MSG_USERAUTH_REQUEST); ++ packet_put_cstring(authctxt->server_user); ++ packet_put_cstring(authctxt->service); ++ packet_put_cstring(authctxt->method->name); ++ packet_put_string(mic.value, mic.length); ++ packet_send(); ++ ++ buffer_free(&b); ++ gss_release_buffer(&ms, &mic); ++ ++ return (1); ++} ++ + #endif /* GSSAPI */ + + int +diff -up openssh-6.1p1/sshd.c.gsskex openssh-6.1p1/sshd.c +--- openssh-6.1p1/sshd.c.gsskex 2012-09-14 20:57:55.799266515 +0200 ++++ openssh-6.1p1/sshd.c 2012-09-14 20:57:55.912267237 +0200 +@@ -124,6 +124,10 @@ + #include "ssh-sandbox.h" + #include "version.h" + ++#ifdef USE_SECURITY_SESSION_API ++#include ++#endif ++ + #ifdef LIBWRAP + #include + #include +@@ -1692,10 +1696,13 @@ main(int ac, char **av) + logit("Disabling protocol version 1. Could not load host key"); + options.protocol &= ~SSH_PROTO_1; + } ++#ifndef GSSAPI ++ /* The GSSAPI key exchange can run without a host key */ + if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) { + logit("Disabling protocol version 2. Could not load host key"); + options.protocol &= ~SSH_PROTO_2; + } ++#endif + if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { + logit("sshd: no hostkeys available -- exiting."); + exit(1); +@@ -2027,6 +2034,60 @@ main(int ac, char **av) + /* Log the connection. */ + verbose("Connection from %.500s port %d", remote_ip, remote_port); + ++#ifdef USE_SECURITY_SESSION_API ++ /* ++ * Create a new security session for use by the new user login if ++ * the current session is the root session or we are not launched ++ * by inetd (eg: debugging mode or server mode). We do not ++ * necessarily need to create a session if we are launched from ++ * inetd because Panther xinetd will create a session for us. ++ * ++ * The only case where this logic will fail is if there is an ++ * inetd running in a non-root session which is not creating ++ * new sessions for us. Then all the users will end up in the ++ * same session (bad). ++ * ++ * When the client exits, the session will be destroyed for us ++ * automatically. ++ * ++ * We must create the session before any credentials are stored ++ * (including AFS pags, which happens a few lines below). ++ */ ++ { ++ OSStatus err = 0; ++ SecuritySessionId sid = 0; ++ SessionAttributeBits sattrs = 0; ++ ++ err = SessionGetInfo(callerSecuritySession, &sid, &sattrs); ++ if (err) ++ error("SessionGetInfo() failed with error %.8X", ++ (unsigned) err); ++ else ++ debug("Current Session ID is %.8X / Session Attributes are %.8X", ++ (unsigned) sid, (unsigned) sattrs); ++ ++ if (inetd_flag && !(sattrs & sessionIsRoot)) ++ debug("Running in inetd mode in a non-root session... " ++ "assuming inetd created the session for us."); ++ else { ++ debug("Creating new security session..."); ++ err = SessionCreate(0, sessionHasTTY | sessionIsRemote); ++ if (err) ++ error("SessionCreate() failed with error %.8X", ++ (unsigned) err); ++ ++ err = SessionGetInfo(callerSecuritySession, &sid, ++ &sattrs); ++ if (err) ++ error("SessionGetInfo() failed with error %.8X", ++ (unsigned) err); ++ else ++ debug("New Session ID is %.8X / Session Attributes are %.8X", ++ (unsigned) sid, (unsigned) sattrs); ++ } ++ } ++#endif ++ + /* + * We don't want to listen forever unless the other side + * successfully authenticates itself. So we set up an alarm which is +@@ -2425,6 +2486,48 @@ do_ssh2_kex(void) + + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types(); + ++#ifdef GSSAPI ++ { ++ char *orig; ++ char *gss = NULL; ++ char *newstr = NULL; ++ orig = myproposal[PROPOSAL_KEX_ALGS]; ++ ++ /* ++ * If we don't have a host key, then there's no point advertising ++ * the other key exchange algorithms ++ */ ++ ++ if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) ++ orig = NULL; ++ ++ if (options.gss_keyex) ++ gss = ssh_gssapi_server_mechanisms(); ++ else ++ gss = NULL; ++ ++ if (gss && orig) ++ xasprintf(&newstr, "%s,%s", gss, orig); ++ else if (gss) ++ newstr = gss; ++ else if (orig) ++ newstr = orig; ++ ++ /* ++ * If we've got GSSAPI mechanisms, then we've got the 'null' host ++ * key alg, but we can't tell people about it unless its the only ++ * host key algorithm we support ++ */ ++ if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) ++ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null"; ++ ++ if (newstr) ++ myproposal[PROPOSAL_KEX_ALGS] = newstr; ++ else ++ fatal("No supported key exchange algorithms"); ++ } ++#endif ++ + /* start key exchange */ + kex = kex_setup(myproposal); + kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; +@@ -2432,6 +2535,13 @@ do_ssh2_kex(void) + kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; + kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; + kex->kex[KEX_ECDH_SHA2] = kexecdh_server; ++#ifdef GSSAPI ++ if (options.gss_keyex) { ++ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; ++ } ++#endif + kex->server = 1; + kex->client_version_string=client_version_string; + kex->server_version_string=server_version_string; +diff -up openssh-6.1p1/sshd_config.gsskex openssh-6.1p1/sshd_config +--- openssh-6.1p1/sshd_config.gsskex 2012-09-14 20:57:55.801266528 +0200 ++++ openssh-6.1p1/sshd_config 2012-09-14 20:57:55.916267263 +0200 +@@ -85,6 +85,8 @@ ChallengeResponseAuthentication no + GSSAPIAuthentication yes + #GSSAPICleanupCredentials yes + GSSAPICleanupCredentials yes ++#GSSAPIStrictAcceptorCheck yes ++#GSSAPIKeyExchange no + + # Set this to 'yes' to enable PAM authentication, account processing, + # and session processing. If this is enabled, PAM authentication will +diff -up openssh-6.1p1/sshd_config.5.gsskex openssh-6.1p1/sshd_config.5 +--- openssh-6.1p1/sshd_config.5.gsskex 2012-09-14 20:57:55.767266310 +0200 ++++ openssh-6.1p1/sshd_config.5 2012-09-14 20:57:55.915267256 +0200 +@@ -439,12 +439,40 @@ Specifies whether user authentication ba + The default is + .Dq no . + Note that this option applies to protocol version 2 only. ++.It Cm GSSAPIKeyExchange ++Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange ++doesn't rely on ssh keys to verify host identity. ++The default is ++.Dq no . ++Note that this option applies to protocol version 2 only. + .It Cm GSSAPICleanupCredentials + Specifies whether to automatically destroy the user's credentials cache + on logout. + The default is + .Dq yes . + Note that this option applies to protocol version 2 only. ++.It Cm GSSAPIStrictAcceptorCheck ++Determines whether to be strict about the identity of the GSSAPI acceptor ++a client authenticates against. If ++.Dq yes ++then the client must authenticate against the ++.Pa host ++service on the current hostname. If ++.Dq no ++then the client may authenticate against any service key stored in the ++machine's default store. This facility is provided to assist with operation ++on multi homed machines. ++The default is ++.Dq yes . ++Note that this option applies only to protocol version 2 GSSAPI connections, ++and setting it to ++.Dq no ++may only work with recent Kerberos GSSAPI libraries. ++.It Cm GSSAPIStoreCredentialsOnRekey ++Controls whether the user's GSSAPI credentials should be updated following a ++successful connection rekeying. This option can be used to accepted renewed ++or updated credentials from a compatible client. The default is ++.Dq no . + .It Cm HostbasedAuthentication + Specifies whether rhosts or /etc/hosts.equiv authentication together + with successful public key client host authentication is allowed +diff -up openssh-6.1p1/ssh-gss.h.gsskex openssh-6.1p1/ssh-gss.h +--- openssh-6.1p1/ssh-gss.h.gsskex 2007-06-12 15:40:39.000000000 +0200 ++++ openssh-6.1p1/ssh-gss.h 2012-09-14 20:57:55.918267275 +0200 +@@ -1,6 +1,6 @@ + /* $OpenBSD: ssh-gss.h,v 1.10 2007/06/12 08:20:00 djm Exp $ */ + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -60,10 +60,22 @@ + + #define SSH_GSS_OIDTYPE 0x06 + ++#define SSH2_MSG_KEXGSS_INIT 30 ++#define SSH2_MSG_KEXGSS_CONTINUE 31 ++#define SSH2_MSG_KEXGSS_COMPLETE 32 ++#define SSH2_MSG_KEXGSS_HOSTKEY 33 ++#define SSH2_MSG_KEXGSS_ERROR 34 ++#define SSH2_MSG_KEXGSS_GROUPREQ 40 ++#define SSH2_MSG_KEXGSS_GROUP 41 ++#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" ++#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" ++#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" ++ + typedef struct { + char *filename; + char *envvar; + char *envval; ++ struct passwd *owner; + void *data; + } ssh_gssapi_ccache; + +@@ -71,8 +83,11 @@ typedef struct { + gss_buffer_desc displayname; + gss_buffer_desc exportedname; + gss_cred_id_t creds; ++ gss_name_t name; + struct ssh_gssapi_mech_struct *mech; + ssh_gssapi_ccache store; ++ int used; ++ int updated; + } ssh_gssapi_client; + + typedef struct ssh_gssapi_mech_struct { +@@ -83,6 +98,7 @@ typedef struct ssh_gssapi_mech_struct { + int (*userok) (ssh_gssapi_client *, char *); + int (*localname) (ssh_gssapi_client *, char **); + void (*storecreds) (ssh_gssapi_client *); ++ int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); + } ssh_gssapi_mech; + + typedef struct { +@@ -93,10 +109,11 @@ typedef struct { + gss_OID oid; /* client */ + gss_cred_id_t creds; /* server */ + gss_name_t client; /* server */ +- gss_cred_id_t client_creds; /* server */ ++ gss_cred_id_t client_creds; /* both */ + } Gssctxt; + + extern ssh_gssapi_mech *supported_mechs[]; ++extern Gssctxt *gss_kex_context; + + int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); + void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); +@@ -116,16 +133,30 @@ void ssh_gssapi_build_ctx(Gssctxt **); + void ssh_gssapi_delete_ctx(Gssctxt **); + OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); + void ssh_gssapi_buildmic(Buffer *, const char *, const char *, const char *); +-int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); ++int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); ++OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); ++int ssh_gssapi_credentials_updated(Gssctxt *); + + /* In the server */ ++typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, ++ const char *); ++char *ssh_gssapi_client_mechanisms(const char *, const char *); ++char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, ++ const char *); ++gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); ++int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, ++ const char *); + OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); +-int ssh_gssapi_userok(char *name); ++int ssh_gssapi_userok(char *name, struct passwd *); + OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); + void ssh_gssapi_do_child(char ***, u_int *); + void ssh_gssapi_cleanup_creds(void); + void ssh_gssapi_storecreds(void); + ++char *ssh_gssapi_server_mechanisms(void); ++int ssh_gssapi_oid_table_ok(); ++ ++int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); + #endif /* GSSAPI */ + + #endif /* _SSH_GSS_H */ diff --git a/openssh-6.1p1-kuserok.patch b/openssh-6.1p1-kuserok.patch new file mode 100644 index 0000000..7b695e0 --- /dev/null +++ b/openssh-6.1p1-kuserok.patch @@ -0,0 +1,167 @@ +diff -up openssh-6.1p1/auth-krb5.c.kuserok openssh-6.1p1/auth-krb5.c +--- openssh-6.1p1/auth-krb5.c.kuserok 2012-09-14 21:08:16.941496194 +0200 ++++ openssh-6.1p1/auth-krb5.c 2012-09-14 21:08:17.063496896 +0200 +@@ -55,6 +55,20 @@ + + extern ServerOptions options; + ++int ++ssh_krb5_kuserok(krb5_context krb5_ctx, krb5_principal krb5_user, const char *client) ++{ ++ if (options.use_kuserok) ++ return krb5_kuserok(krb5_ctx, krb5_user, client); ++ else { ++ char kuser[65]; ++ ++ if (krb5_aname_to_localname(krb5_ctx, krb5_user, sizeof(kuser), kuser)) ++ return 0; ++ return strcmp(kuser, client) == 0; ++ } ++} ++ + static int + krb5_init(void *context) + { +@@ -147,7 +161,7 @@ auth_krb5_password(Authctxt *authctxt, c + if (problem) + goto out; + +- if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) { ++ if (!ssh_krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) { + problem = -1; + goto out; + } +diff -up openssh-6.1p1/gss-serv-krb5.c.kuserok openssh-6.1p1/gss-serv-krb5.c +--- openssh-6.1p1/gss-serv-krb5.c.kuserok 2012-09-14 21:08:17.019496642 +0200 ++++ openssh-6.1p1/gss-serv-krb5.c 2012-09-14 21:08:17.065496906 +0200 +@@ -68,6 +68,7 @@ static int ssh_gssapi_krb5_cmdok(krb5_pr + int); + + static krb5_context krb_context = NULL; ++extern int ssh_krb5_kuserok(krb5_context, krb5_principal, const char *); + + /* Initialise the krb5 library, for the stuff that GSSAPI won't do */ + +@@ -115,7 +116,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client + /* NOTE: .k5login and .k5users must opened as root, not the user, + * because if they are on a krb5-protected filesystem, user credentials + * to access these files aren't available yet. */ +- if (krb5_kuserok(krb_context, princ, luser) && k5login_exists) { ++ if (ssh_krb5_kuserok(krb_context, princ, luser) && k5login_exists) { + retval = 1; + logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", + luser, (char *)client->displayname.value); +diff -up openssh-6.1p1/servconf.c.kuserok openssh-6.1p1/servconf.c +--- openssh-6.1p1/servconf.c.kuserok 2012-09-14 21:08:16.989496471 +0200 ++++ openssh-6.1p1/servconf.c 2012-09-14 21:09:30.864868698 +0200 +@@ -152,6 +152,7 @@ initialize_server_options(ServerOptions + options->ip_qos_interactive = -1; + options->ip_qos_bulk = -1; + options->version_addendum = NULL; ++ options->use_kuserok = -1; + } + + void +@@ -301,6 +302,8 @@ fill_default_server_options(ServerOption + options->version_addendum = xstrdup(""); + if (options->show_patchlevel == -1) + options->show_patchlevel = 0; ++ if (options->use_kuserok == -1) ++ options->use_kuserok = 1; + + /* Turn privilege separation on by default */ + if (use_privsep == -1) +@@ -327,7 +330,7 @@ typedef enum { + sPermitRootLogin, sLogFacility, sLogLevel, + sRhostsRSAAuthentication, sRSAAuthentication, + sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, +- sKerberosGetAFSToken, ++ sKerberosGetAFSToken, sKerberosUseKuserok, + sKerberosTgtPassing, sChallengeResponseAuthentication, + sPasswordAuthentication, sKbdInteractiveAuthentication, + sListenAddress, sAddressFamily, +@@ -399,11 +402,13 @@ static struct { + #else + { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, + #endif ++ { "kerberosusekuserok", sKerberosUseKuserok, SSHCFG_ALL }, + #else + { "kerberosauthentication", sUnsupported, SSHCFG_ALL }, + { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL }, + { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL }, + { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, ++ { "kerberosusekuserok", sUnsupported, SSHCFG_ALL }, + #endif + { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, + { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, +@@ -1486,6 +1491,10 @@ process_server_config_line(ServerOptions + *activep = value; + break; + ++ case sKerberosUseKuserok: ++ intptr = &options->use_kuserok; ++ goto parse_flag; ++ + case sPermitOpen: + arg = strdelim(&cp); + if (!arg || *arg == '\0') +@@ -1769,6 +1778,7 @@ copy_set_server_options(ServerOptions *d + M_CP_INTOPT(max_authtries); + M_CP_INTOPT(ip_qos_interactive); + M_CP_INTOPT(ip_qos_bulk); ++ M_CP_INTOPT(use_kuserok); + + /* See comment in servconf.h */ + COPY_MATCH_STRING_OPTS(); +@@ -2005,6 +2015,7 @@ dump_config(ServerOptions *o) + dump_cfg_fmtint(sUseDNS, o->use_dns); + dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); + dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); ++ dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok); + + /* string arguments */ + dump_cfg_string(sPidFile, o->pid_file); +diff -up openssh-6.1p1/servconf.h.kuserok openssh-6.1p1/servconf.h +--- openssh-6.1p1/servconf.h.kuserok 2012-09-14 21:08:16.990496476 +0200 ++++ openssh-6.1p1/servconf.h 2012-09-14 21:08:17.071496942 +0200 +@@ -169,6 +169,7 @@ typedef struct { + + int num_permitted_opens; + ++ int use_kuserok; + char *chroot_directory; + char *revoked_keys_file; + char *trusted_user_ca_keys; +diff -up openssh-6.1p1/sshd_config.kuserok openssh-6.1p1/sshd_config +--- openssh-6.1p1/sshd_config.kuserok 2012-09-14 21:08:17.002496545 +0200 ++++ openssh-6.1p1/sshd_config 2012-09-14 21:08:17.074496957 +0200 +@@ -79,6 +79,7 @@ ChallengeResponseAuthentication no + #KerberosOrLocalPasswd yes + #KerberosTicketCleanup yes + #KerberosGetAFSToken no ++#KerberosUseKuserok yes + + # GSSAPI options + #GSSAPIAuthentication no +diff -up openssh-6.1p1/sshd_config.5.kuserok openssh-6.1p1/sshd_config.5 +--- openssh-6.1p1/sshd_config.5.kuserok 2012-09-14 21:08:17.004496556 +0200 ++++ openssh-6.1p1/sshd_config.5 2012-09-14 21:08:17.073496952 +0200 +@@ -618,6 +618,10 @@ Specifies whether to automatically destr + file on logout. + The default is + .Dq yes . ++.It Cm KerberosUseKuserok ++Specifies whether to look at .k5login file for user's aliases. ++The default is ++.Dq yes . + .It Cm KexAlgorithms + Specifies the available KEX (Key Exchange) algorithms. + Multiple algorithms must be comma-separated. +@@ -767,6 +771,7 @@ Available keywords are + .Cm HostbasedUsesNameFromPacketOnly , + .Cm KbdInteractiveAuthentication , + .Cm KerberosAuthentication , ++.Cm KerberosUseKuserok , + .Cm MaxAuthTries , + .Cm MaxSessions , + .Cm PubkeyAuthentication , diff --git a/openssh-6.1p1-log-usepam-no.patch b/openssh-6.1p1-log-usepam-no.patch new file mode 100644 index 0000000..4ed52b1 --- /dev/null +++ b/openssh-6.1p1-log-usepam-no.patch @@ -0,0 +1,26 @@ +diff -up openssh-6.1p1/sshd.c.log-usepam-no openssh-6.1p1/sshd.c +--- openssh-6.1p1/sshd.c.log-usepam-no 2012-09-14 20:54:58.000000000 +0200 ++++ openssh-6.1p1/sshd.c 2012-09-14 20:55:42.289477749 +0200 +@@ -1617,6 +1617,10 @@ main(int ac, char **av) + parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, + &cfg, NULL); + ++ /* 'UsePAM no' is not supported in Fedora */ ++ if (! options.use_pam) ++ logit("WARNING: 'UsePAM no' is not supported in Fedora and may cause several problems."); ++ + seed_rng(); + + /* Fill in default values for those options not explicitly set. */ +diff -up openssh-6.1p1/sshd_config.log-usepam-no openssh-6.1p1/sshd_config +--- openssh-6.1p1/sshd_config.log-usepam-no 2012-09-14 20:54:58.514255748 +0200 ++++ openssh-6.1p1/sshd_config 2012-09-14 20:54:58.551255954 +0200 +@@ -95,6 +95,8 @@ GSSAPICleanupCredentials yes + # If you just want the PAM account and session checks to run without + # PAM authentication, then enable this but set PasswordAuthentication + # and ChallengeResponseAuthentication to 'no'. ++# WARNING: 'UsePAM no' is not supported in Fedora and may cause several ++# problems. + #UsePAM no + UsePAM yes + diff --git a/openssh-6.1p1-required-authentications.patch b/openssh-6.1p1-required-authentications.patch new file mode 100644 index 0000000..d10606a --- /dev/null +++ b/openssh-6.1p1-required-authentications.patch @@ -0,0 +1,828 @@ +diff -up openssh-6.1p1/auth.c.required-authentication openssh-6.1p1/auth.c +--- openssh-6.1p1/auth.c.required-authentication 2012-09-14 20:17:56.730488188 +0200 ++++ openssh-6.1p1/auth.c 2012-09-14 20:17:56.795488498 +0200 +@@ -251,7 +251,8 @@ allowed_user(struct passwd * pw) + } + + void +-auth_log(Authctxt *authctxt, int authenticated, char *method, char *info) ++auth_log(Authctxt *authctxt, int authenticated, const char *method, ++ const char *submethod, const char *info) + { + void (*authlog) (const char *fmt,...) = verbose; + char *authmsg; +@@ -271,9 +272,10 @@ auth_log(Authctxt *authctxt, int authent + else + authmsg = authenticated ? "Accepted" : "Failed"; + +- authlog("%s %s for %s%.100s from %.200s port %d%s", ++ authlog("%s %s%s%s for %s%.100s from %.200s port %d%s", + authmsg, + method, ++ submethod == NULL ? "" : "/", submethod == NULL ? "" : submethod, + authctxt->valid ? "" : "invalid user ", + authctxt->user, + get_remote_ipaddr(), +@@ -303,7 +305,7 @@ auth_log(Authctxt *authctxt, int authent + * Check whether root logins are disallowed. + */ + int +-auth_root_allowed(char *method) ++auth_root_allowed(const char *method) + { + switch (options.permit_root_login) { + case PERMIT_YES: +@@ -696,3 +698,57 @@ fakepw(void) + + return (&fake); + } ++ ++int ++auth_method_in_list(const char *list, const char *method) ++{ ++ char *cp; ++ ++ cp = match_list(method, list, NULL); ++ if (cp != NULL) { ++ xfree(cp); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++#define DELIM "," ++int ++auth_remove_from_list(char **list, const char *method) ++{ ++ char *oldlist, *cp, *newlist = NULL; ++ u_int len = 0, ret = 0; ++ ++ if (list == NULL || *list == NULL) ++ return (0); ++ ++ oldlist = *list; ++ len = strlen(oldlist) + 1; ++ newlist = xmalloc(len); ++ memset(newlist, '\0', len); ++ ++ /* Remove method from list, if present */ ++ for (;;) { ++ if ((cp = strsep(&oldlist, DELIM)) == NULL) ++ break; ++ if (*cp == '\0') ++ continue; ++ if (strcmp(cp, method) != 0) { ++ if (*newlist != '\0') ++ strlcat(newlist, DELIM, len); ++ strlcat(newlist, cp, len); ++ } else ++ ret++; ++ } ++ ++ /* Return NULL instead of empty list */ ++ if (*newlist == '\0') { ++ xfree(newlist); ++ newlist = NULL; ++ } ++ xfree(*list); ++ *list = newlist; ++ ++ return (ret); ++} +diff -up openssh-6.1p1/auth.h.required-authentication openssh-6.1p1/auth.h +--- openssh-6.1p1/auth.h.required-authentication 2011-05-29 13:39:38.000000000 +0200 ++++ openssh-6.1p1/auth.h 2012-09-14 20:17:56.796488502 +0200 +@@ -142,10 +142,11 @@ void disable_forwarding(void); + void do_authentication(Authctxt *); + void do_authentication2(Authctxt *); + +-void auth_log(Authctxt *, int, char *, char *); +-void userauth_finish(Authctxt *, int, char *); ++void auth_log(Authctxt *, int, const char *, const char *, const char *); ++void userauth_finish(Authctxt *, int, const char *, const char *); ++int auth_root_allowed(const char *); ++ + void userauth_send_banner(const char *); +-int auth_root_allowed(char *); + + char *auth2_read_banner(void); + +@@ -192,6 +193,11 @@ void auth_debug_send(void); + void auth_debug_reset(void); + + struct passwd *fakepw(void); ++int auth_method_in_list(const char *, const char *); ++int auth_remove_from_list(char **, const char *); ++ ++int auth1_check_required(const char *); ++int auth2_check_required(const char *); + + int sys_auth_passwd(Authctxt *, const char *); + +diff -up openssh-6.1p1/auth1.c.required-authentication openssh-6.1p1/auth1.c +--- openssh-6.1p1/auth1.c.required-authentication 2010-08-31 14:36:39.000000000 +0200 ++++ openssh-6.1p1/auth1.c 2012-09-14 20:17:56.798488515 +0200 +@@ -98,6 +98,55 @@ static const struct AuthMethod1 + return (NULL); + } + ++static const struct AuthMethod1 * ++lookup_authmethod1_by_name(const char *name) ++{ ++ int i; ++ ++ for (i = 0; auth1_methods[i].name != NULL; i++) ++ if (strcmp(auth1_methods[i].name, name) == 0) ++ return (&(auth1_methods[i])); ++ ++ return NULL; ++} ++ ++#define DELIM "," ++int ++auth1_check_required(const char *list) ++{ ++ char *orig_methods, *methods, *cp; ++ static const struct AuthMethod1 *m; ++ int ret = 0; ++ ++ orig_methods = methods = xstrdup(list); ++ for(;;) { /* XXX maybe: while ((cp = ...) != NULL) ? */ ++ if ((cp = strsep(&methods, DELIM)) == NULL) ++ break; ++ debug2("auth1_check_required: method \"%s\"", cp); ++ if (*cp == '\0') { ++ debug("auth1_check_required: empty method"); ++ ret = -1; ++ } ++ if ((m = lookup_authmethod1_by_name(cp)) == NULL) { ++ debug("auth1_check_required: unknown method " ++ "\"%s\"", cp); ++ ret = -1; ++ break; ++ } ++ if (*(m->enabled) == 0) { ++ debug("auth1_check_required: method %s explicitly " ++ "disabled", cp); ++ ret = -1; ++ } ++ /* Activate method if it isn't already */ ++ if (*(m->enabled) == -1) ++ *(m->enabled) = 1; ++ } ++ xfree(orig_methods); ++ return (ret); ++} ++ ++ + static char * + get_authname(int type) + { +@@ -237,6 +286,7 @@ do_authloop(Authctxt *authctxt) + { + int authenticated = 0; + char info[1024]; ++ const char *meth_name; + int prev = 0, type = 0; + const struct AuthMethod1 *meth; + +@@ -244,7 +294,7 @@ do_authloop(Authctxt *authctxt) + authctxt->valid ? "" : "invalid user ", authctxt->user); + + /* If the user has no password, accept authentication immediately. */ +- if (options.permit_empty_passwd && options.password_authentication && ++ if (options.permit_empty_passwd && options.password_authentication && options.password_authentication && + #ifdef KRB5 + (!options.kerberos_authentication || options.kerberos_or_local_passwd) && + #endif +@@ -253,7 +303,7 @@ do_authloop(Authctxt *authctxt) + if (options.use_pam && (PRIVSEP(do_pam_account()))) + #endif + { +- auth_log(authctxt, 1, "without authentication", ""); ++ auth_log(authctxt, 1, "without authentication", NULL, ""); + return; + } + } +@@ -272,6 +322,7 @@ do_authloop(Authctxt *authctxt) + /* Get a packet from the client. */ + prev = type; + type = packet_read(); ++ meth_name = get_authname(type); + + /* + * If we started challenge-response authentication but the +@@ -287,8 +338,8 @@ do_authloop(Authctxt *authctxt) + if (authctxt->failures >= options.max_authtries) + goto skip; + if ((meth = lookup_authmethod1(type)) == NULL) { +- logit("Unknown message during authentication: " +- "type %d", type); ++ logit("Unknown message during authentication: type %d", ++ type); + goto skip; + } + +@@ -297,6 +348,17 @@ do_authloop(Authctxt *authctxt) + goto skip; + } + ++ /* ++ * Skip methods not in required list, until all the required ++ * ones are done ++ */ ++ if (options.required_auth1 != NULL && ++ !auth_method_in_list(options.required_auth1, meth_name)) { ++ debug("Skipping method \"%s\" until required " ++ "authentication completed", meth_name); ++ goto skip; ++ } ++ + authenticated = meth->method(authctxt, info, sizeof(info)); + if (authenticated == -1) + continue; /* "postponed" */ +@@ -352,7 +414,29 @@ do_authloop(Authctxt *authctxt) + + skip: + /* Log before sending the reply */ +- auth_log(authctxt, authenticated, get_authname(type), info); ++ auth_log(authctxt, authenticated, meth_name, NULL, info); ++ ++ /* Loop until the required authmethods are done */ ++ if (authenticated && options.required_auth1 != NULL) { ++ if (auth_remove_from_list(&options.required_auth1, ++ meth_name) == 0) ++ fatal("INTERNAL ERROR: authenticated method " ++ "\"%s\" not in required list \"%s\"", ++ meth_name, options.required_auth1); ++ debug2("do_authloop: required list now: %s", ++ options.required_auth1 == NULL ? ++ "DONE" : options.required_auth1); ++ if (options.required_auth1 == NULL) ++ return; ++ authenticated = 0; ++ /* ++ * Disable method so client can't authenticate with it ++ * after the required authentications are complete. ++ */ ++ *(meth->enabled) = 0; ++ packet_send_debug("Further authentication required"); ++ goto send_fail; ++ } + + if (client_user != NULL) { + xfree(client_user); +@@ -368,6 +452,7 @@ do_authloop(Authctxt *authctxt) + #endif + packet_disconnect(AUTH_FAIL_MSG, authctxt->user); + } ++ send_fail: + + packet_start(SSH_SMSG_FAILURE); + packet_send(); +diff -up openssh-6.1p1/auth2.c.required-authentication openssh-6.1p1/auth2.c +--- openssh-6.1p1/auth2.c.required-authentication 2011-12-19 00:52:51.000000000 +0100 ++++ openssh-6.1p1/auth2.c 2012-09-14 20:17:56.799488520 +0200 +@@ -215,7 +215,7 @@ input_userauth_request(int type, u_int32 + { + Authctxt *authctxt = ctxt; + Authmethod *m = NULL; +- char *user, *service, *method, *style = NULL; ++ char *user, *service, *method, *active_methods, *style = NULL; + int authenticated = 0; + + if (authctxt == NULL) +@@ -277,22 +277,31 @@ input_userauth_request(int type, u_int32 + authctxt->server_caused_failure = 0; + + /* try to authenticate user */ +- m = authmethod_lookup(method); +- if (m != NULL && authctxt->failures < options.max_authtries) { +- debug2("input_userauth_request: try method %s", method); +- authenticated = m->userauth(authctxt); +- } +- userauth_finish(authctxt, authenticated, method); ++ active_methods = authmethods_get(); ++ if (strcmp(method, "none") == 0 || ++ auth_method_in_list(active_methods, method)) { ++ m = authmethod_lookup(method); ++ if (m != NULL) { ++ debug2("input_userauth_request: try method %s", method); ++ authenticated = m->userauth(authctxt); ++ } + ++ } ++ xfree(active_methods); ++ userauth_finish(authctxt, authenticated, method, NULL); ++ + xfree(service); + xfree(user); + xfree(method); + } + + void +-userauth_finish(Authctxt *authctxt, int authenticated, char *method) ++userauth_finish(Authctxt *authctxt, int authenticated, const char *method, ++ const char *submethod) + { + char *methods; ++ Authmethod *m = NULL; ++ u_int partial = 0; + + if (!authctxt->valid && authenticated) + fatal("INTERNAL ERROR: authenticated invalid user %s", +@@ -330,12 +339,42 @@ userauth_finish(Authctxt *authctxt, int + #endif /* _UNICOS */ + + /* Log before sending the reply */ +- auth_log(authctxt, authenticated, method, " ssh2"); ++ auth_log(authctxt, authenticated, method, submethod, " ssh2"); + + if (authctxt->postponed) + return; + +- /* XXX todo: check if multiple auth methods are needed */ ++ /* Handle RequiredAuthentications2: loop until required methods done */ ++ if (authenticated && options.required_auth2 != NULL) { ++ if ((m = authmethod_lookup(method)) == NULL) ++ fatal("INTERNAL ERROR: authenticated method " ++ "\"%s\" unknown", method); ++ if (auth_remove_from_list(&options.required_auth2, method) == 0) ++ fatal("INTERNAL ERROR: authenticated method " ++ "\"%s\" not in required list \"%s\"", ++ method, options.required_auth2); ++ debug2("userauth_finish: required list now: %s", ++ options.required_auth2 == NULL ? ++ "DONE" : options.required_auth2); ++ /* ++ * if authenticated and no more required methods ++ * then declare success ++ */ ++ if ( authenticated && options.required_auth2 == NULL ) { ++ debug2("userauth_finish: authenticated and no more required methods"); ++ } else { ++ /* ++ * Disable method so client can't authenticate with it after ++ * the required authentications are complete. ++ */ ++ if (m->enabled != NULL) ++ *(m->enabled) = 0; ++ authenticated = 0; ++ partial = 1; ++ goto send_fail; ++ } ++ } ++ + if (authenticated == 1) { + /* turn off userauth */ + dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); +@@ -345,7 +384,6 @@ userauth_finish(Authctxt *authctxt, int + /* now we can break out */ + authctxt->success = 1; + } else { +- + /* Allow initial try of "none" auth without failure penalty */ + if (!authctxt->server_caused_failure && + (authctxt->attempt > 1 || strcmp(method, "none") != 0)) +@@ -356,10 +394,11 @@ userauth_finish(Authctxt *authctxt, int + #endif + packet_disconnect(AUTH_FAIL_MSG, authctxt->user); + } ++ send_fail: + methods = authmethods_get(); + packet_start(SSH2_MSG_USERAUTH_FAILURE); + packet_put_cstring(methods); +- packet_put_char(0); /* XXX partial success, unused */ ++ packet_put_char(partial); + packet_send(); + packet_write_wait(); + xfree(methods); +@@ -373,6 +412,9 @@ authmethods_get(void) + char *list; + int i; + ++ if (options.required_auth2 != NULL) ++ return xstrdup(options.required_auth2); ++ + buffer_init(&b); + for (i = 0; authmethods[i] != NULL; i++) { + if (strcmp(authmethods[i]->name, "none") == 0) +@@ -407,3 +449,43 @@ authmethod_lookup(const char *name) + return NULL; + } + ++#define DELIM "," ++ ++int ++auth2_check_required(const char *list) ++{ ++ char *orig_methods, *methods, *cp; ++ struct Authmethod *m; ++ int i, ret = 0; ++ ++ orig_methods = methods = xstrdup(list); ++ for(;;) { ++ if ((cp = strsep(&methods, DELIM)) == NULL) ++ break; ++ debug2("auth2_check_required: method \"%s\"", cp); ++ if (*cp == '\0') { ++ debug("auth2_check_required: empty method"); ++ ret = -1; ++ } ++ for (i = 0; authmethods[i] != NULL; i++) ++ if (strcmp(cp, authmethods[i]->name) == 0) ++ break; ++ if ((m = authmethods[i]) == NULL) { ++ debug("auth2_check_required: unknown method " ++ "\"%s\"", cp); ++ ret = -1; ++ break; ++ } ++ if (m->enabled == NULL || *(m->enabled) == 0) { ++ debug("auth2_check_required: method %s explicitly " ++ "disabled", cp); ++ ret = -1; ++ } ++ /* Activate method if it isn't already */ ++ if (m->enabled != NULL && *(m->enabled) == -1) ++ *(m->enabled) = 1; ++ } ++ xfree(orig_methods); ++ return (ret); ++} ++ +diff -up openssh-6.1p1/auth2-gss.c.required-authentication openssh-6.1p1/auth2-gss.c +--- openssh-6.1p1/auth2-gss.c.required-authentication 2011-05-05 06:04:11.000000000 +0200 ++++ openssh-6.1p1/auth2-gss.c 2012-09-14 20:17:56.801488528 +0200 +@@ -163,7 +163,7 @@ input_gssapi_token(int type, u_int32_t p + } + authctxt->postponed = 0; + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); +- userauth_finish(authctxt, 0, "gssapi-with-mic"); ++ userauth_finish(authctxt, 0, "gssapi-with-mic", NULL); + } else { + if (send_tok.length != 0) { + packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN); +@@ -251,7 +251,7 @@ input_gssapi_exchange_complete(int type, + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); +- userauth_finish(authctxt, authenticated, "gssapi-with-mic"); ++ userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); + } + + static void +@@ -291,7 +291,7 @@ input_gssapi_mic(int type, u_int32_t ple + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL); + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL); + dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL); +- userauth_finish(authctxt, authenticated, "gssapi-with-mic"); ++ userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); + } + + Authmethod method_gssapi = { +diff -up openssh-6.1p1/auth2-chall.c.required-authentication openssh-6.1p1/auth2-chall.c +--- openssh-6.1p1/auth2-chall.c.required-authentication 2009-01-28 06:13:39.000000000 +0100 ++++ openssh-6.1p1/auth2-chall.c 2012-09-14 20:17:56.802488532 +0200 +@@ -341,7 +341,8 @@ input_userauth_info_response(int type, u + auth2_challenge_start(authctxt); + } + } +- userauth_finish(authctxt, authenticated, method); ++ userauth_finish(authctxt, authenticated, "keyboard-interactive", ++ authctxt->kbdintctxt?kbdintctxt->device->name:NULL); + xfree(method); + } + +diff -up openssh-6.1p1/auth2-none.c.required-authentication openssh-6.1p1/auth2-none.c +--- openssh-6.1p1/auth2-none.c.required-authentication 2010-06-26 02:01:33.000000000 +0200 ++++ openssh-6.1p1/auth2-none.c 2012-09-14 20:17:56.803488537 +0200 +@@ -61,7 +61,7 @@ userauth_none(Authctxt *authctxt) + { + none_enabled = 0; + packet_check_eom(); +- if (options.permit_empty_passwd && options.password_authentication) ++ if (options.permit_empty_passwd && options.password_authentication && options.required_auth2 == NULL) + return (PRIVSEP(auth_password(authctxt, ""))); + return (0); + } +diff -up openssh-6.1p1/monitor.c.required-authentication openssh-6.1p1/monitor.c +--- openssh-6.1p1/monitor.c.required-authentication 2012-09-14 20:17:56.685487974 +0200 ++++ openssh-6.1p1/monitor.c 2012-09-14 20:17:56.806488552 +0200 +@@ -199,6 +199,7 @@ static int key_blobtype = MM_NOKEY; + static char *hostbased_cuser = NULL; + static char *hostbased_chost = NULL; + static char *auth_method = "unknown"; ++static char *auth_submethod = NULL; + static u_int session_id2_len = 0; + static u_char *session_id2 = NULL; + static pid_t monitor_child_pid; +@@ -353,6 +354,7 @@ monitor_child_preauth(Authctxt *_authctx + { + struct mon_table *ent; + int authenticated = 0; ++ char **req_auth; + + debug3("preauth child monitor started"); + +@@ -367,12 +369,14 @@ monitor_child_preauth(Authctxt *_authctx + + if (compat20) { + mon_dispatch = mon_dispatch_proto20; ++ req_auth = &options.required_auth2; + + /* Permit requests for moduli and signatures */ + monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); + monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); + } else { + mon_dispatch = mon_dispatch_proto15; ++ req_auth = &options.required_auth1; + + monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); + } +@@ -380,6 +384,7 @@ monitor_child_preauth(Authctxt *_authctx + /* The first few requests do not require asynchronous access */ + while (!authenticated) { + auth_method = "unknown"; ++ auth_submethod = NULL; + authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1); + if (authenticated) { + if (!(ent->flags & MON_AUTHDECIDE)) +@@ -401,10 +406,19 @@ monitor_child_preauth(Authctxt *_authctx + } + #endif + } ++ /* Loop until the required authmethods are done */ ++ if (authenticated && *req_auth != NULL) { ++ if (auth_remove_from_list(req_auth, auth_method) == 0) ++ fatal("INTERNAL ERROR: authenticated method " ++ "\"%s\" not in required list \"%s\"", ++ auth_method, *req_auth); ++ debug2("monitor_child_preauth: required list now: %s", ++ *req_auth == NULL ? "DONE" : *req_auth); ++ } + + if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { + auth_log(authctxt, authenticated, auth_method, +- compat20 ? " ssh2" : ""); ++ auth_submethod, compat20 ? " ssh2" : ""); + if (!authenticated) + authctxt->failures++; + } +@@ -417,6 +431,8 @@ monitor_child_preauth(Authctxt *_authctx + } + } + #endif ++ if (*req_auth != NULL) ++ authenticated = 0; + } + + /* Drain any buffered messages from the child */ +@@ -860,6 +876,7 @@ mm_answer_authpassword(int sock, Buffer + auth_method = "none"; + else + auth_method = "password"; ++ auth_submethod = NULL; + + /* Causes monitor loop to terminate if authenticated */ + return (authenticated); +@@ -919,6 +936,7 @@ mm_answer_bsdauthrespond(int sock, Buffe + mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m); + + auth_method = "bsdauth"; ++ auth_submethod = NULL; + + return (authok != 0); + } +@@ -968,6 +986,7 @@ mm_answer_skeyrespond(int sock, Buffer * + mm_request_send(sock, MONITOR_ANS_SKEYRESPOND, m); + + auth_method = "skey"; ++ auth_submethod = NULL; + + return (authok != 0); + } +@@ -1057,7 +1076,8 @@ mm_answer_pam_query(int sock, Buffer *m) + xfree(prompts); + if (echo_on != NULL) + xfree(echo_on); +- auth_method = "keyboard-interactive/pam"; ++ auth_method = "keyboard-interactive"; ++ auth_submethod = "pam"; + mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m); + return (0); + } +@@ -1086,7 +1106,8 @@ mm_answer_pam_respond(int sock, Buffer * + buffer_clear(m); + buffer_put_int(m, ret); + mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m); +- auth_method = "keyboard-interactive/pam"; ++ auth_method = "keyboard-interactive"; ++ auth_submethod = "pam"; + if (ret == 0) + sshpam_authok = sshpam_ctxt; + return (0); +@@ -1100,7 +1121,8 @@ mm_answer_pam_free_ctx(int sock, Buffer + (sshpam_device.free_ctx)(sshpam_ctxt); + buffer_clear(m); + mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m); +- auth_method = "keyboard-interactive/pam"; ++ auth_method = "keyboard-interactive"; ++ auth_submethod = "pam"; + return (sshpam_authok == sshpam_ctxt); + } + #endif +@@ -1136,6 +1158,7 @@ mm_answer_keyallowed(int sock, Buffer *m + allowed = options.pubkey_authentication && + user_key_allowed(authctxt->pw, key); + auth_method = "publickey"; ++ auth_submethod = NULL; + if (options.pubkey_authentication && allowed != 1) + auth_clear_options(); + break; +@@ -1144,6 +1167,7 @@ mm_answer_keyallowed(int sock, Buffer *m + hostbased_key_allowed(authctxt->pw, + cuser, chost, key); + auth_method = "hostbased"; ++ auth_submethod = NULL; + break; + case MM_RSAHOSTKEY: + key->type = KEY_RSA1; /* XXX */ +@@ -1153,6 +1177,7 @@ mm_answer_keyallowed(int sock, Buffer *m + if (options.rhosts_rsa_authentication && allowed != 1) + auth_clear_options(); + auth_method = "rsa"; ++ auth_submethod = NULL; + break; + default: + fatal("%s: unknown key type %d", __func__, type); +@@ -1178,7 +1203,8 @@ mm_answer_keyallowed(int sock, Buffer *m + hostbased_chost = chost; + } else { + /* Log failed attempt */ +- auth_log(authctxt, 0, auth_method, compat20 ? " ssh2" : ""); ++ auth_log(authctxt, 0, auth_method, auth_submethod, ++ compat20 ? " ssh2" : ""); + xfree(blob); + xfree(cuser); + xfree(chost); +@@ -1354,6 +1380,7 @@ mm_answer_keyverify(int sock, Buffer *m) + xfree(data); + + auth_method = key_blobtype == MM_USERKEY ? "publickey" : "hostbased"; ++ auth_submethod = NULL; + + monitor_reset_key_state(); + +@@ -1543,6 +1570,7 @@ mm_answer_rsa_keyallowed(int sock, Buffe + debug3("%s entering", __func__); + + auth_method = "rsa"; ++ auth_submethod = NULL; + if (options.rsa_authentication && authctxt->valid) { + if ((client_n = BN_new()) == NULL) + fatal("%s: BN_new", __func__); +@@ -1648,6 +1676,7 @@ mm_answer_rsa_response(int sock, Buffer + xfree(response); + + auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa"; ++ auth_submethod = NULL; + + /* reset state */ + BN_clear_free(ssh1_challenge); +@@ -2097,6 +2126,7 @@ mm_answer_gss_userok(int sock, Buffer *m + mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); + + auth_method = "gssapi-with-mic"; ++ auth_submethod = NULL; + + /* Monitor loop will terminate if authenticated */ + return (authenticated); +@@ -2301,6 +2331,7 @@ mm_answer_jpake_check_confirm(int sock, + monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 1); + + auth_method = "jpake-01@openssh.com"; ++ auth_submethod = NULL; + return authenticated; + } + +diff -up openssh-6.1p1/servconf.c.required-authentication openssh-6.1p1/servconf.c +--- openssh-6.1p1/servconf.c.required-authentication 2012-09-14 20:17:56.699488040 +0200 ++++ openssh-6.1p1/servconf.c 2012-09-14 20:19:49.179983651 +0200 +@@ -43,6 +43,8 @@ + #include "key.h" + #include "kex.h" + #include "mac.h" ++#include "hostfile.h" ++#include "auth.h" + #include "match.h" + #include "channels.h" + #include "groupaccess.h" +@@ -132,6 +134,8 @@ initialize_server_options(ServerOptions + options->num_authkeys_files = 0; + options->num_accept_env = 0; + options->permit_tun = -1; ++ options->required_auth1 = NULL; ++ options->required_auth2 = NULL; + options->num_permitted_opens = -1; + options->adm_forced_command = NULL; + options->chroot_directory = NULL; +@@ -324,6 +328,7 @@ typedef enum { + sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, + sClientAliveCountMax, sAuthorizedKeysFile, + sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, ++ sRequiredAuthentications1, sRequiredAuthentications2, + sMatch, sPermitOpen, sForceCommand, sChrootDirectory, + sUsePrivilegeSeparation, sAllowAgentForwarding, + sZeroKnowledgePasswordAuthentication, sHostCertificate, +@@ -452,6 +457,8 @@ static struct { + { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, + { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, + { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, ++ { "requiredauthentications1", sRequiredAuthentications1, SSHCFG_ALL }, ++ { "requiredauthentications2", sRequiredAuthentications2, SSHCFG_ALL }, + { "ipqos", sIPQoS, SSHCFG_ALL }, + { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, + { NULL, sBadOption, 0 } +@@ -1298,6 +1305,33 @@ process_server_config_line(ServerOptions + options->max_startups = options->max_startups_begin; + break; + ++ ++ case sRequiredAuthentications1: ++ charptr = &options->required_auth1; ++ arg = strdelim(&cp); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", ++ filename, linenum); ++ if (auth1_check_required(arg) != 0) ++ fatal("%.200s line %d: Invalid required authentication " ++ "list", filename, linenum); ++ if (*charptr == NULL) ++ *charptr = xstrdup(arg); ++ break; ++ ++ case sRequiredAuthentications2: ++ charptr = &options->required_auth2; ++ arg = strdelim(&cp); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", ++ filename, linenum); ++ if (auth2_check_required(arg) != 0) ++ fatal("%.200s line %d: Invalid required authentication " ++ "list", filename, linenum); ++ if (*charptr == NULL) ++ *charptr = xstrdup(arg); ++ break; ++ + case sMaxAuthTries: + intptr = &options->max_authtries; + goto parse_int; +diff -up openssh-6.1p1/servconf.h.required-authentication openssh-6.1p1/servconf.h +--- openssh-6.1p1/servconf.h.required-authentication 2012-07-31 04:21:34.000000000 +0200 ++++ openssh-6.1p1/servconf.h 2012-09-14 20:17:56.810488571 +0200 +@@ -154,6 +154,9 @@ typedef struct { + u_int num_authkeys_files; /* Files containing public keys */ + char *authorized_keys_files[MAX_AUTHKEYS_FILES]; + ++ char *required_auth1; /* Required, but not sufficient */ ++ char *required_auth2; ++ + char *adm_forced_command; + + int use_pam; /* Enable auth via PAM */ +diff -up openssh-6.1p1/sshd_config.5.required-authentication openssh-6.1p1/sshd_config.5 +--- openssh-6.1p1/sshd_config.5.required-authentication 2012-07-02 10:53:38.000000000 +0200 ++++ openssh-6.1p1/sshd_config.5 2012-09-14 20:17:56.812488582 +0200 +@@ -731,6 +731,8 @@ Available keywords are + .Cm PermitOpen , + .Cm PermitRootLogin , + .Cm PermitTunnel , ++.Cm RequiredAuthentications1, ++.Cm RequiredAuthentications2, + .Cm PubkeyAuthentication , + .Cm RhostsRSAAuthentication , + .Cm RSAAuthentication , +@@ -931,6 +933,21 @@ Specifies a list of revoked public keys. + Keys listed in this file will be refused for public key authentication. + Note that if this file is not readable, then public key authentication will + be refused for all users. ++.It Cm RequiredAuthentications[12] ++ Specifies required methods of authentications that has to succeed before authorizing the connection. ++ (RequiredAuthentication1 for Protocol version 1, and RequiredAuthentication2 for v2) ++ ++ RequiredAuthentications1 method[,method...] ++ RequiredAuthentications2 method[,method...] ++ ++.Pp ++Example 1: ++ ++ RequiredAuthentications2 password,hostbased ++ ++Example 2: ++ RequiredAuthentications2 publickey,password ++ + .It Cm RhostsRSAAuthentication + Specifies whether rhosts or /etc/hosts.equiv authentication together + with successful RSA host authentication is allowed. diff --git a/openssh-6.1p1-vendor.patch b/openssh-6.1p1-vendor.patch new file mode 100644 index 0000000..9cb326d --- /dev/null +++ b/openssh-6.1p1-vendor.patch @@ -0,0 +1,158 @@ +diff -up openssh-6.1p1/configure.ac.vendor openssh-6.1p1/configure.ac +--- openssh-6.1p1/configure.ac.vendor 2012-09-14 20:36:49.153085211 +0200 ++++ openssh-6.1p1/configure.ac 2012-09-14 20:36:49.559088133 +0200 +@@ -4303,6 +4303,12 @@ AC_ARG_WITH([lastlog], + fi + ] + ) ++AC_ARG_ENABLE(vendor-patchlevel, ++ [ --enable-vendor-patchlevel=TAG specify a vendor patch level], ++ [AC_DEFINE_UNQUOTED(SSH_VENDOR_PATCHLEVEL,[SSH_RELEASE "-" "$enableval"],[Define to your vendor patch level, if it has been modified from the upstream source release.]) ++ SSH_VENDOR_PATCHLEVEL="$enableval"], ++ [AC_DEFINE(SSH_VENDOR_PATCHLEVEL,SSH_RELEASE,[Define to your vendor patch level, if it has been modified from the upstream source release.]) ++ SSH_VENDOR_PATCHLEVEL=none]) + + dnl lastlog, [uw]tmpx? detection + dnl NOTE: set the paths in the platform section to avoid the +@@ -4529,6 +4535,7 @@ echo " Translate v4 in v6 hack + echo " BSD Auth support: $BSD_AUTH_MSG" + echo " Random number source: $RAND_MSG" + echo " Privsep sandbox style: $SANDBOX_STYLE" ++echo " Vendor patch level: $SSH_VENDOR_PATCHLEVEL" + + echo "" + +diff -up openssh-6.1p1/servconf.c.vendor openssh-6.1p1/servconf.c +--- openssh-6.1p1/servconf.c.vendor 2012-09-14 20:36:49.124085002 +0200 ++++ openssh-6.1p1/servconf.c 2012-09-14 20:50:34.995972516 +0200 +@@ -128,6 +128,7 @@ initialize_server_options(ServerOptions + options->max_authtries = -1; + options->max_sessions = -1; + options->banner = NULL; ++ options->show_patchlevel = -1; + options->use_dns = -1; + options->client_alive_interval = -1; + options->client_alive_count_max = -1; +@@ -289,6 +290,9 @@ fill_default_server_options(ServerOption + options->ip_qos_bulk = IPTOS_THROUGHPUT; + if (options->version_addendum == NULL) + options->version_addendum = xstrdup(""); ++ if (options->show_patchlevel == -1) ++ options->show_patchlevel = 0; ++ + /* Turn privilege separation on by default */ + if (use_privsep == -1) + use_privsep = PRIVSEP_NOSANDBOX; +@@ -326,7 +330,7 @@ typedef enum { + sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, + sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, + sMaxStartups, sMaxAuthTries, sMaxSessions, +- sBanner, sUseDNS, sHostbasedAuthentication, ++ sBanner, sShowPatchLevel, sUseDNS, sHostbasedAuthentication, + sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, + sClientAliveCountMax, sAuthorizedKeysFile, + sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, +@@ -441,6 +445,7 @@ static struct { + { "maxauthtries", sMaxAuthTries, SSHCFG_ALL }, + { "maxsessions", sMaxSessions, SSHCFG_ALL }, + { "banner", sBanner, SSHCFG_ALL }, ++ { "showpatchlevel", sShowPatchLevel, SSHCFG_GLOBAL }, + { "usedns", sUseDNS, SSHCFG_GLOBAL }, + { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL }, + { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL }, +@@ -1162,6 +1167,10 @@ process_server_config_line(ServerOptions + multistate_ptr = multistate_privsep; + goto parse_multistate; + ++ case sShowPatchLevel: ++ intptr = &options->show_patchlevel; ++ goto parse_flag; ++ + case sAllowUsers: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (options->num_allow_users >= MAX_ALLOW_USERS) +@@ -1956,6 +1965,7 @@ dump_config(ServerOptions *o) + dump_cfg_fmtint(sUseLogin, o->use_login); + dump_cfg_fmtint(sCompression, o->compression); + dump_cfg_fmtint(sGatewayPorts, o->gateway_ports); ++ dump_cfg_fmtint(sShowPatchLevel, o->show_patchlevel); + dump_cfg_fmtint(sUseDNS, o->use_dns); + dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); + dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); +diff -up openssh-6.1p1/servconf.h.vendor openssh-6.1p1/servconf.h +--- openssh-6.1p1/servconf.h.vendor 2012-09-14 20:36:49.125085009 +0200 ++++ openssh-6.1p1/servconf.h 2012-09-14 20:36:49.564088168 +0200 +@@ -140,6 +140,7 @@ typedef struct { + int max_authtries; + int max_sessions; + char *banner; /* SSH-2 banner message */ ++ int show_patchlevel; /* Show vendor patch level to clients */ + int use_dns; + int client_alive_interval; /* + * poke the client this often to +diff -up openssh-6.1p1/sshd_config.vendor openssh-6.1p1/sshd_config +--- openssh-6.1p1/sshd_config.vendor 2012-09-14 20:36:49.507087759 +0200 ++++ openssh-6.1p1/sshd_config 2012-09-14 20:36:49.565088175 +0200 +@@ -114,6 +114,7 @@ UsePrivilegeSeparation sandbox # Defaul + #Compression delayed + #ClientAliveInterval 0 + #ClientAliveCountMax 3 ++#ShowPatchLevel no + #UseDNS yes + #PidFile /var/run/sshd.pid + #MaxStartups 10 +diff -up openssh-6.1p1/sshd_config.0.vendor openssh-6.1p1/sshd_config.0 +--- openssh-6.1p1/sshd_config.0.vendor 2012-09-14 20:36:49.510087780 +0200 ++++ openssh-6.1p1/sshd_config.0 2012-09-14 20:36:49.567088190 +0200 +@@ -558,6 +558,11 @@ DESCRIPTION + Defines the number of bits in the ephemeral protocol version 1 + server key. The minimum value is 512, and the default is 1024. + ++ ShowPatchLevel ++ Specifies whether sshd will display the specific patch level of ++ the binary in the server identification string. The patch level ++ is set at compile-time. The default is M-bM-^@M-^\noM-bM-^@M-^]. ++ + StrictModes + Specifies whether sshd(8) should check file modes and ownership + of the user's files and home directory before accepting login. +diff -up openssh-6.1p1/sshd_config.5.vendor openssh-6.1p1/sshd_config.5 +--- openssh-6.1p1/sshd_config.5.vendor 2012-09-14 20:36:49.512087794 +0200 ++++ openssh-6.1p1/sshd_config.5 2012-09-14 20:36:49.568088198 +0200 +@@ -978,6 +978,14 @@ This option applies to protocol version + .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. ++.It Cm ShowPatchLevel ++Specifies whether ++.Nm sshd ++will display the patch level of the binary in the identification string. ++The patch level is set at compile-time. ++The default is ++.Dq no . ++This option applies to protocol version 1 only. + .It Cm StrictModes + Specifies whether + .Xr sshd 8 +diff -up openssh-6.1p1/sshd.c.vendor openssh-6.1p1/sshd.c +--- openssh-6.1p1/sshd.c.vendor 2012-09-14 20:36:49.399086981 +0200 ++++ openssh-6.1p1/sshd.c 2012-09-14 20:47:30.696088744 +0200 +@@ -433,7 +433,7 @@ sshd_exchange_identification(int sock_in + } + + xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s", +- major, minor, SSH_VERSION, ++ major, minor, (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION, + *options.version_addendum == '\0' ? "" : " ", + options.version_addendum, newline); + +@@ -1635,7 +1635,8 @@ main(int ac, char **av) + exit(1); + } + +- debug("sshd version %.100s", SSH_RELEASE); ++ debug("sshd version %.100s", ++ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_RELEASE); + + /* Store privilege separation user for later use if required. */ + if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { diff --git a/openssh.spec b/openssh.spec index c909026..87f8fe5 100644 --- a/openssh.spec +++ b/openssh.spec @@ -108,7 +108,7 @@ Source13: sshd-keygen Patch0: openssh-5.9p1-wIm.patch #? -Patch100: openssh-5.9p1-coverity.patch +Patch100: openssh-6.1p1-coverity.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1872 Patch101: openssh-5.8p1-fingerprint.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1894 @@ -118,7 +118,7 @@ Patch102: openssh-5.8p1-getaddrinfo.patch Patch103: openssh-5.8p1-packet.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=983 #Patch104: openssh-5.9p1-2auth.patch -Patch104: openssh-5.9p1-required-authentications.patch +Patch104: openssh-6.1p1-required-authentications.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1402 Patch200: openssh-5.8p1-audit0.patch @@ -150,7 +150,7 @@ Patch402: openssh-5.9p1-sftp-chroot.patch Patch404: openssh-5.9p1-privsep-selinux.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1663 -Patch500: openssh-5.9p1-akc.patch +Patch500: openssh-6.1p1-akc.patch #?-- unwanted child :( Patch501: openssh-6.0p1-ldap.patch #? @@ -173,7 +173,7 @@ Patch606: openssh-5.9p1-ipv6man.patch #? Patch607: openssh-5.8p2-sigpipe.patch #? -Patch608: openssh-5.8p2-askpass-ld.patch +Patch608: openssh-6.1p1-askpass-ld.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1789 Patch609: openssh-5.5p1-x11.patch @@ -196,29 +196,27 @@ Patch707: openssh-5.9p1-redhat.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1890 (WONTFIX) need integration to prng helper which is discontinued :) Patch708: openssh-6.0p1-entropy.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1640 (WONTFIX) -Patch709: openssh-5.9p1-vendor.patch +Patch709: openssh-6.1p1-vendor.patch #? Patch710: openssh-5.9p1-copy-id-restorecon.patch # warn users for unsupported UsePAM=no (#757545) -Patch711: openssh-5.9p1-log-usepam-no.patch +Patch711: openssh-6.1p1-log-usepam-no.patch # make aes-ctr ciphers use EVP engines such as AES-NI from OpenSSL Patch712: openssh-5.9p1-ctr-evp-fast.patch # add cavs test binary for the aes-ctr Patch713: openssh-5.9p1-ctr-cavstest.patch -#https://bugzilla.redhat.com/show_bug.cgi?id=815993 -Patch714: openssh-5.9p1-null-xcrypt.patch #http://www.sxw.org.uk/computing/patches/openssh.html #changed cache storage type - #848228 -Patch800: openssh-6.0p1-gsskex.patch +Patch800: openssh-6.1p1-gsskex.patch #http://www.mail-archive.com/kerberos@mit.edu/msg17591.html Patch801: openssh-5.8p2-force_krb.patch #? Patch900: openssh-5.8p1-gssapi-canohost.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1780 -Patch901: openssh-5.9p1-kuserok.patch +Patch901: openssh-6.1p1-kuserok.patch #--- #https://bugzilla.mindrot.org/show_bug.cgi?id=1604 # sctp @@ -459,7 +457,6 @@ popd %patch711 -p1 -b .log-usepam-no %patch712 -p1 -b .evp-ctr %patch713 -p1 -b .ctr-cavs -%patch714 -p0 -b .null-xcrypt %patch800 -p1 -b .gsskex %patch801 -p1 -b .force_krb