diff --git a/.gitignore b/.gitignore index a37509f..1be2547 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ openssh-5.5p1-noacss.tar.bz2 pam_ssh_agent_auth-0.9.2.tar.bz2 /openssh-5.6p1-noacss.tar.bz2 /pam_ssh_agent_auth-0.9.2.tar.bz2 +/openssh-5.8p1-noacss.tar.bz2 diff --git a/openssh-4.3p1-fromto-remote.patch b/openssh-4.3p1-fromto-remote.patch deleted file mode 100644 index ccb3d6e..0000000 --- a/openssh-4.3p1-fromto-remote.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- openssh-4.3p2/scp.c.fromto-remote 2006-01-31 12:11:38.000000000 +0100 -+++ openssh-4.3p2/scp.c 2006-04-14 10:09:56.000000000 +0200 -@@ -446,7 +446,11 @@ - addargs(&alist, "-v"); - addargs(&alist, "-x"); - addargs(&alist, "-oClearAllForwardings yes"); -- addargs(&alist, "-n"); -+ if (isatty(fileno(stdin))) { -+ addargs(&alist, "-t"); -+ } else { -+ addargs(&alist, "-n"); -+ } - - *src++ = 0; - if (*src == 0) diff --git a/openssh-4.3p2-gssapi-canohost.patch b/openssh-4.3p2-gssapi-canohost.patch deleted file mode 100644 index 2ad07d5..0000000 --- a/openssh-4.3p2-gssapi-canohost.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff -up openssh-5.3p1/sshconnect2.c.canohost openssh-5.3p1/sshconnect2.c ---- openssh-5.3p1/sshconnect2.c.canohost 2009-03-05 14:58:22.000000000 +0100 -+++ openssh-5.3p1/sshconnect2.c 2009-11-02 11:55:00.000000000 +0100 -@@ -542,6 +542,12 @@ userauth_gssapi(Authctxt *authctxt) - static u_int mech = 0; - OM_uint32 min; - int ok = 0; -+ char* remotehost = NULL; -+ const char* canonicalhost = get_canonical_hostname(1); -+ if ( strcmp( canonicalhost, "UNKNOWN" ) == 0 ) -+ remotehost = authctxt->host; -+ else -+ remotehost = canonicalhost; - - /* Try one GSSAPI method at a time, rather than sending them all at - * once. */ -@@ -554,7 +560,7 @@ userauth_gssapi(Authctxt *authctxt) - /* 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], remotehost)) { - ok = 1; /* Mechanism works */ - } else { - mech++; diff --git a/openssh-5.2p1-vendor.patch b/openssh-5.2p1-vendor.patch deleted file mode 100644 index f6db132..0000000 --- a/openssh-5.2p1-vendor.patch +++ /dev/null @@ -1,158 +0,0 @@ -diff -up openssh-5.2p1/configure.ac.vendor openssh-5.2p1/configure.ac ---- openssh-5.2p1/configure.ac.vendor 2008-07-23 14:13:22.000000000 +0200 -+++ openssh-5.2p1/configure.ac 2008-07-23 14:13:22.000000000 +0200 -@@ -3890,6 +3890,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 -@@ -4146,6 +4152,7 @@ echo " IP address in \$DISPLAY hac - echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" - echo " BSD Auth support: $BSD_AUTH_MSG" - echo " Random number source: $RAND_MSG" -+echo " Vendor patch level: $SSH_VENDOR_PATCHLEVEL" - if test ! -z "$USE_RAND_HELPER" ; then - echo " ssh-rand-helper collects from: $RAND_HELPER_MSG" - fi -diff -up openssh-5.2p1/sshd_config.5.vendor openssh-5.2p1/sshd_config.5 ---- openssh-5.2p1/sshd_config.5.vendor 2008-07-23 14:13:22.000000000 +0200 -+++ openssh-5.2p1/sshd_config.5 2008-07-23 14:19:23.000000000 +0200 -@@ -812,6 +812,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.2p1/servconf.h.vendor openssh-5.2p1/servconf.h ---- openssh-5.2p1/servconf.h.vendor 2008-06-10 15:01:51.000000000 +0200 -+++ openssh-5.2p1/servconf.h 2008-07-23 14:13:22.000000000 +0200 -@@ -126,6 +126,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.2p1/servconf.c.vendor openssh-5.2p1/servconf.c ---- openssh-5.2p1/servconf.c.vendor 2008-07-04 05:51:12.000000000 +0200 -+++ openssh-5.2p1/servconf.c 2008-07-23 14:32:27.000000000 +0200 -@@ -117,6 +117,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; -@@ -262,6 +263,9 @@ fill_default_server_options(ServerOption - if (options->zero_knowledge_password_authentication == -1) - options->zero_knowledge_password_authentication = 0; - -+ if (options->show_patchlevel == -1) -+ options->show_patchlevel = 0; -+ - /* Turn privilege separation on by default */ - if (use_privsep == -1) - use_privsep = 1; -@@ -299,7 +303,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, sAuthorizedKeysFile2, - sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, -@@ -410,6 +414,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 }, -@@ -1033,6 +1038,10 @@ process_server_config_line(ServerOptions - intptr = &use_privsep; - goto parse_flag; - -+ 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) -@@ -1613,6 +1622,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.2p1/sshd_config.0.vendor openssh-5.2p1/sshd_config.0 ---- openssh-5.2p1/sshd_config.0.vendor 2008-07-23 14:13:22.000000000 +0200 -+++ openssh-5.2p1/sshd_config.0 2008-07-23 14:13:22.000000000 +0200 -@@ -466,6 +466,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.2p1/sshd_config.vendor openssh-5.2p1/sshd_config ---- openssh-5.2p1/sshd_config.vendor 2008-07-23 14:13:22.000000000 +0200 -+++ openssh-5.2p1/sshd_config 2008-07-23 14:13:22.000000000 +0200 -@@ -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.2p1/sshd.c.vendor openssh-5.2p1/sshd.c ---- openssh-5.2p1/sshd.c.vendor 2008-07-11 09:36:49.000000000 +0200 -+++ openssh-5.2p1/sshd.c 2008-07-23 14:35:43.000000000 +0200 -@@ -416,7 +416,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. */ -@@ -1484,7 +1484,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-5.3p1-randclean.patch b/openssh-5.3p1-randclean.patch deleted file mode 100644 index 61a56d1..0000000 --- a/openssh-5.3p1-randclean.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -up openssh-5.3p1/entropy.c.randclean openssh-5.3p1/entropy.c ---- openssh-5.3p1/entropy.c.randclean 2010-01-21 09:26:30.000000000 +0100 -+++ openssh-5.3p1/entropy.c 2010-01-21 09:26:37.000000000 +0100 -@@ -159,6 +159,9 @@ init_rng(void) - fatal("OpenSSL version mismatch. Built against %lx, you " - "have %lx", OPENSSL_VERSION_NUMBER, SSLeay()); - -+ /* clean the PRNG status when exiting the program */ -+ atexit(RAND_cleanup); -+ - #ifndef OPENSSL_PRNG_ONLY - original_uid = getuid(); - original_euid = geteuid(); diff --git a/openssh-5.4p1-pam_selinux.patch b/openssh-5.4p1-pam_selinux.patch deleted file mode 100644 index 6b601da..0000000 --- a/openssh-5.4p1-pam_selinux.patch +++ /dev/null @@ -1,156 +0,0 @@ -diff -up openssh-5.4p1/auth-pam.c.pam_selinux openssh-5.4p1/auth-pam.c ---- openssh-5.4p1/auth-pam.c.pam_selinux 2009-07-12 14:07:21.000000000 +0200 -+++ openssh-5.4p1/auth-pam.c 2010-03-01 15:27:23.000000000 +0100 -@@ -1069,7 +1069,7 @@ is_pam_session_open(void) - * during the ssh authentication process. - */ - int --do_pam_putenv(char *name, char *value) -+do_pam_putenv(char *name, const char *value) - { - int ret = 1; - #ifdef HAVE_PAM_PUTENV -diff -up openssh-5.4p1/auth-pam.h.pam_selinux openssh-5.4p1/auth-pam.h ---- openssh-5.4p1/auth-pam.h.pam_selinux 2004-09-11 14:17:26.000000000 +0200 -+++ openssh-5.4p1/auth-pam.h 2010-03-01 15:27:23.000000000 +0100 -@@ -38,7 +38,7 @@ void do_pam_session(void); - void do_pam_set_tty(const char *); - void do_pam_setcred(int ); - void do_pam_chauthtok(void); --int do_pam_putenv(char *, char *); -+int do_pam_putenv(char *, const char *); - char ** fetch_pam_environment(void); - char ** fetch_pam_child_environment(void); - void free_pam_environment(char **); -diff -up openssh-5.4p1/openbsd-compat/port-linux.c.pam_selinux openssh-5.4p1/openbsd-compat/port-linux.c ---- openssh-5.4p1/openbsd-compat/port-linux.c.pam_selinux 2010-03-01 15:27:22.000000000 +0100 -+++ openssh-5.4p1/openbsd-compat/port-linux.c 2010-03-01 15:27:53.000000000 +0100 -@@ -36,6 +36,7 @@ - #include "hostfile.h" - #include "auth.h" - #include "xmalloc.h" -+#include "servconf.h" - - #ifdef WITH_SELINUX - #include -@@ -50,6 +51,7 @@ - #include - #endif - -+extern ServerOptions options; - extern Authctxt *the_authctxt; - extern int inetd_flag; - extern int rexeced_flag; -@@ -211,29 +213,38 @@ get_user_context(const char *sename, con - return -1; - } - -+static void -+ssh_selinux_get_role_level(char **role, const char **level) -+{ -+ *role = NULL; -+ *level = NULL; -+ if (the_authctxt) { -+ if (the_authctxt->role != NULL) { -+ char *slash; -+ *role = xstrdup(the_authctxt->role); -+ if ((slash = strchr(*role, '/')) != NULL) { -+ *slash = '\0'; -+ *level = slash + 1; -+ } -+ } -+ } -+} -+ - /* Return the default security context for the given username */ - static int - ssh_selinux_getctxbyname(char *pwname, - security_context_t *default_sc, security_context_t *user_sc) - { - char *sename, *lvl; -- const char *reqlvl = NULL; -- char *role = NULL; -+ const char *reqlvl; -+ char *role; - int r = -1; - context_t con = NULL; - - *default_sc = NULL; - *user_sc = NULL; -- if (the_authctxt) { -- if (the_authctxt->role != NULL) { -- char *slash; -- role = xstrdup(the_authctxt->role); -- if ((slash = strchr(role, '/')) != NULL) { -- *slash = '\0'; -- reqlvl = slash + 1; -- } -- } -- } -+ -+ ssh_selinux_get_role_level(&role, &reqlvl); - - #ifdef HAVE_GETSEUSERBYNAME - if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) { -@@ -314,6 +325,36 @@ ssh_selinux_getctxbyname(char *pwname, - return (r); - } - -+/* Setup environment variables for pam_selinux */ -+static int -+ssh_selinux_setup_pam_variables(void) -+{ -+ const char *reqlvl; -+ char *role; -+ char *use_current; -+ int rv; -+ -+ debug3("%s: setting execution context", __func__); -+ -+ ssh_selinux_get_role_level(&role, &reqlvl); -+ -+ rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : ""); -+ -+ if (inetd_flag && !rexeced_flag) { -+ use_current = "1"; -+ } else { -+ use_current = ""; -+ rv = rv || do_pam_putenv("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: ""); -+ } -+ -+ rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current); -+ -+ if (role != NULL) -+ xfree(role); -+ -+ return rv; -+} -+ - /* Set the execution context to the default for the specified user */ - void - ssh_selinux_setup_exec_context(char *pwname) -@@ -325,6 +366,24 @@ ssh_selinux_setup_exec_context(char *pwn - if (!ssh_selinux_enabled()) - return; - -+ if (options.use_pam) { -+ /* do not compute context, just setup environment for pam_selinux */ -+ if (ssh_selinux_setup_pam_variables()) { -+ switch (security_getenforce()) { -+ case -1: -+ fatal("%s: security_getenforce() failed", __func__); -+ case 0: -+ error("%s: SELinux PAM variable setup failure. Continuing in permissive mode.", -+ __func__); -+ break; -+ default: -+ fatal("%s: SELinux PAM variable setup failure. Aborting connection.", -+ __func__); -+ } -+ } -+ return; -+ } -+ - debug3("%s: setting execution context", __func__); - - r = ssh_selinux_getctxbyname(pwname, &default_ctx, &user_ctx); diff --git a/openssh-5.4p1-selinux.patch b/openssh-5.4p1-selinux.patch deleted file mode 100644 index 465811f..0000000 --- a/openssh-5.4p1-selinux.patch +++ /dev/null @@ -1,395 +0,0 @@ -diff -up openssh-5.4p1/auth1.c.selinux openssh-5.4p1/auth1.c ---- openssh-5.4p1/auth1.c.selinux 2010-03-01 15:19:56.000000000 +0100 -+++ openssh-5.4p1/auth1.c 2010-03-01 15:19:57.000000000 +0100 -@@ -384,6 +384,9 @@ do_authentication(Authctxt *authctxt) - { - u_int ulen; - char *user, *style = NULL; -+#ifdef WITH_SELINUX -+ char *role=NULL; -+#endif - - /* Get the name of the user that we wish to log in as. */ - packet_read_expect(SSH_CMSG_USER); -@@ -392,11 +395,25 @@ do_authentication(Authctxt *authctxt) - user = packet_get_string(&ulen); - packet_check_eom(); - -+#ifdef WITH_SELINUX -+ if ((role = strchr(user, '/')) != NULL) -+ *role++ = '\0'; -+#endif -+ - if ((style = strchr(user, ':')) != NULL) - *style++ = '\0'; -+#ifdef WITH_SELINUX -+ else -+ if (role && (style = strchr(role, ':')) != NULL) -+ *style++ = '\0'; -+#endif -+ - - authctxt->user = user; - authctxt->style = style; -+#ifdef WITH_SELINUX -+ authctxt->role = role; -+#endif - - /* Verify that the user is a valid user. */ - if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) -diff -up openssh-5.4p1/auth2.c.selinux openssh-5.4p1/auth2.c ---- openssh-5.4p1/auth2.c.selinux 2009-06-22 08:11:07.000000000 +0200 -+++ openssh-5.4p1/auth2.c 2010-03-01 15:19:57.000000000 +0100 -@@ -216,6 +216,9 @@ input_userauth_request(int type, u_int32 - Authctxt *authctxt = ctxt; - Authmethod *m = NULL; - char *user, *service, *method, *style = NULL; -+#ifdef WITH_SELINUX -+ char *role = NULL; -+#endif - int authenticated = 0; - - if (authctxt == NULL) -@@ -227,6 +230,11 @@ input_userauth_request(int type, u_int32 - debug("userauth-request for user %s service %s method %s", user, service, method); - debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); - -+#ifdef WITH_SELINUX -+ if ((role = strchr(user, '/')) != NULL) -+ *role++ = 0; -+#endif -+ - if ((style = strchr(user, ':')) != NULL) - *style++ = 0; - -@@ -252,8 +260,15 @@ input_userauth_request(int type, u_int32 - use_privsep ? " [net]" : ""); - authctxt->service = xstrdup(service); - authctxt->style = style ? xstrdup(style) : NULL; -- if (use_privsep) -+#ifdef WITH_SELINUX -+ authctxt->role = role ? xstrdup(role) : NULL; -+#endif -+ if (use_privsep) { - mm_inform_authserv(service, style); -+#ifdef WITH_SELINUX -+ mm_inform_authrole(role); -+#endif -+ } - userauth_banner(); - } else if (strcmp(user, authctxt->user) != 0 || - strcmp(service, authctxt->service) != 0) { -diff -up openssh-5.4p1/auth2-gss.c.selinux openssh-5.4p1/auth2-gss.c ---- openssh-5.4p1/auth2-gss.c.selinux 2007-12-02 12:59:45.000000000 +0100 -+++ openssh-5.4p1/auth2-gss.c 2010-03-01 15:19:57.000000000 +0100 -@@ -258,6 +258,7 @@ input_gssapi_mic(int type, u_int32_t ple - Authctxt *authctxt = ctxt; - Gssctxt *gssctxt; - int authenticated = 0; -+ char *micuser; - Buffer b; - gss_buffer_desc mic, gssbuf; - u_int len; -@@ -270,7 +271,13 @@ input_gssapi_mic(int type, u_int32_t ple - mic.value = packet_get_string(&len); - mic.length = len; - -- ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service, -+#ifdef WITH_SELINUX -+ if (authctxt->role && (strlen(authctxt->role) > 0)) -+ xasprintf(&micuser, "%s/%s", authctxt->user, authctxt->role); -+ else -+#endif -+ micuser = authctxt->user; -+ ssh_gssapi_buildmic(&b, micuser, authctxt->service, - "gssapi-with-mic"); - - gssbuf.value = buffer_ptr(&b); -@@ -282,6 +289,8 @@ input_gssapi_mic(int type, u_int32_t ple - logit("GSSAPI MIC check failed"); - - buffer_free(&b); -+ if (micuser != authctxt->user) -+ xfree(micuser); - xfree(mic.value); - - authctxt->postponed = 0; -diff -up openssh-5.4p1/auth2-hostbased.c.selinux openssh-5.4p1/auth2-hostbased.c ---- openssh-5.4p1/auth2-hostbased.c.selinux 2008-07-17 10:57:19.000000000 +0200 -+++ openssh-5.4p1/auth2-hostbased.c 2010-03-01 15:19:57.000000000 +0100 -@@ -106,7 +106,15 @@ userauth_hostbased(Authctxt *authctxt) - buffer_put_string(&b, session_id2, session_id2_len); - /* reconstruct packet */ - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); -- buffer_put_cstring(&b, authctxt->user); -+#ifdef WITH_SELINUX -+ if (authctxt->role) { -+ buffer_put_int(&b, strlen(authctxt->user)+strlen(authctxt->role)+1); -+ buffer_append(&b, authctxt->user, strlen(authctxt->user)); -+ buffer_put_char(&b, '/'); -+ buffer_append(&b, authctxt->role, strlen(authctxt->role)); -+ } else -+#endif -+ buffer_put_cstring(&b, authctxt->user); - buffer_put_cstring(&b, service); - buffer_put_cstring(&b, "hostbased"); - buffer_put_string(&b, pkalg, alen); -diff -up openssh-5.4p1/auth2-pubkey.c.selinux openssh-5.4p1/auth2-pubkey.c ---- openssh-5.4p1/auth2-pubkey.c.selinux 2010-02-26 21:55:05.000000000 +0100 -+++ openssh-5.4p1/auth2-pubkey.c 2010-03-01 15:19:57.000000000 +0100 -@@ -119,7 +119,15 @@ userauth_pubkey(Authctxt *authctxt) - } - /* reconstruct packet */ - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); -- buffer_put_cstring(&b, authctxt->user); -+#ifdef WITH_SELINUX -+ if (authctxt->role) { -+ buffer_put_int(&b, strlen(authctxt->user)+strlen(authctxt->role)+1); -+ buffer_append(&b, authctxt->user, strlen(authctxt->user)); -+ buffer_put_char(&b, '/'); -+ buffer_append(&b, authctxt->role, strlen(authctxt->role)); -+ } else -+#endif -+ buffer_put_cstring(&b, authctxt->user); - buffer_put_cstring(&b, - datafellows & SSH_BUG_PKSERVICE ? - "ssh-userauth" : -diff -up openssh-5.4p1/auth.h.selinux openssh-5.4p1/auth.h ---- openssh-5.4p1/auth.h.selinux 2010-02-26 21:55:05.000000000 +0100 -+++ openssh-5.4p1/auth.h 2010-03-01 15:19:57.000000000 +0100 -@@ -58,6 +58,9 @@ struct Authctxt { - char *service; - struct passwd *pw; /* set if 'valid' */ - char *style; -+#ifdef WITH_SELINUX -+ char *role; -+#endif - void *kbdintctxt; - void *jpake_ctx; - #ifdef BSD_AUTH -diff -up openssh-5.4p1/configure.ac.selinux openssh-5.4p1/configure.ac ---- openssh-5.4p1/configure.ac.selinux 2010-03-01 15:19:57.000000000 +0100 -+++ openssh-5.4p1/configure.ac 2010-03-01 15:21:12.000000000 +0100 -@@ -3358,6 +3358,7 @@ AC_ARG_WITH(selinux, - ], - AC_MSG_ERROR(SELinux support requires libselinux library)) - SSHDLIBS="$SSHDLIBS $LIBSELINUX" -+ LIBS="$LIBS $LIBSELINUX" - AC_CHECK_FUNCS(getseuserbyname get_default_context_with_level) - LIBS="$save_LIBS" - fi ] -diff -up openssh-5.4p1/monitor.c.selinux openssh-5.4p1/monitor.c ---- openssh-5.4p1/monitor.c.selinux 2010-02-26 21:55:05.000000000 +0100 -+++ openssh-5.4p1/monitor.c 2010-03-01 15:19:57.000000000 +0100 -@@ -137,6 +137,9 @@ int mm_answer_sign(int, Buffer *); - int mm_answer_pwnamallow(int, Buffer *); - int mm_answer_auth2_read_banner(int, Buffer *); - int mm_answer_authserv(int, Buffer *); -+#ifdef WITH_SELINUX -+int mm_answer_authrole(int, Buffer *); -+#endif - int mm_answer_authpassword(int, Buffer *); - int mm_answer_bsdauthquery(int, Buffer *); - int mm_answer_bsdauthrespond(int, Buffer *); -@@ -213,6 +216,9 @@ struct mon_table mon_dispatch_proto20[] - {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, - {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, - {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, -+#ifdef WITH_SELINUX -+ {MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole}, -+#endif - {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, - {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, - #ifdef USE_PAM -@@ -682,6 +688,9 @@ mm_answer_pwnamallow(int sock, Buffer *m - else { - /* Allow service/style information on the auth context */ - monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); -+#ifdef WITH_SELINUX -+ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHROLE, 1); -+#endif - monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); - } - -@@ -726,6 +735,25 @@ mm_answer_authserv(int sock, Buffer *m) - return (0); - } - -+#ifdef WITH_SELINUX -+int -+mm_answer_authrole(int sock, Buffer *m) -+{ -+ monitor_permit_authentications(1); -+ -+ authctxt->role = buffer_get_string(m, NULL); -+ debug3("%s: role=%s", -+ __func__, authctxt->role); -+ -+ if (strlen(authctxt->role) == 0) { -+ xfree(authctxt->role); -+ authctxt->role = NULL; -+ } -+ -+ return (0); -+} -+#endif -+ - int - mm_answer_authpassword(int sock, Buffer *m) - { -@@ -1104,7 +1132,7 @@ static int - monitor_valid_userblob(u_char *data, u_int datalen) - { - Buffer b; -- char *p; -+ char *p, *r; - u_int len; - int fail = 0; - -@@ -1130,6 +1158,8 @@ monitor_valid_userblob(u_char *data, u_i - if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) - fail++; - p = buffer_get_string(&b, NULL); -+ if ((r = strchr(p, '/')) != NULL) -+ *r = '\0'; - if (strcmp(authctxt->user, p) != 0) { - logit("wrong user name passed to monitor: expected %s != %.100s", - authctxt->user, p); -@@ -1161,7 +1191,7 @@ monitor_valid_hostbasedblob(u_char *data - char *chost) - { - Buffer b; -- char *p; -+ char *p, *r; - u_int len; - int fail = 0; - -@@ -1178,6 +1208,8 @@ monitor_valid_hostbasedblob(u_char *data - if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) - fail++; - p = buffer_get_string(&b, NULL); -+ if ((r = strchr(p, '/')) != NULL) -+ *r = '\0'; - if (strcmp(authctxt->user, p) != 0) { - logit("wrong user name passed to monitor: expected %s != %.100s", - authctxt->user, p); -diff -up openssh-5.4p1/monitor.h.selinux openssh-5.4p1/monitor.h ---- openssh-5.4p1/monitor.h.selinux 2008-11-05 06:20:46.000000000 +0100 -+++ openssh-5.4p1/monitor.h 2010-03-01 15:19:57.000000000 +0100 -@@ -31,6 +31,9 @@ - enum monitor_reqtype { - MONITOR_REQ_MODULI, MONITOR_ANS_MODULI, - MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV, -+#ifdef WITH_SELINUX -+ MONITOR_REQ_AUTHROLE, -+#endif - MONITOR_REQ_SIGN, MONITOR_ANS_SIGN, - MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM, - MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER, -diff -up openssh-5.4p1/monitor_wrap.c.selinux openssh-5.4p1/monitor_wrap.c ---- openssh-5.4p1/monitor_wrap.c.selinux 2009-06-22 08:11:07.000000000 +0200 -+++ openssh-5.4p1/monitor_wrap.c 2010-03-01 15:19:57.000000000 +0100 -@@ -297,6 +297,25 @@ mm_inform_authserv(char *service, char * - buffer_free(&m); - } - -+/* Inform the privileged process about role */ -+ -+#ifdef WITH_SELINUX -+void -+mm_inform_authrole(char *role) -+{ -+ Buffer m; -+ -+ debug3("%s entering", __func__); -+ -+ buffer_init(&m); -+ buffer_put_cstring(&m, role ? role : ""); -+ -+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, &m); -+ -+ buffer_free(&m); -+} -+#endif -+ - /* Do the password authentication */ - int - mm_auth_password(Authctxt *authctxt, char *password) -diff -up openssh-5.4p1/monitor_wrap.h.selinux openssh-5.4p1/monitor_wrap.h ---- openssh-5.4p1/monitor_wrap.h.selinux 2009-03-05 14:58:22.000000000 +0100 -+++ openssh-5.4p1/monitor_wrap.h 2010-03-01 15:19:57.000000000 +0100 -@@ -41,6 +41,9 @@ int mm_is_monitor(void); - DH *mm_choose_dh(int, int, int); - int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int); - void mm_inform_authserv(char *, char *); -+#ifdef WITH_SELINUX -+void mm_inform_authrole(char *); -+#endif - struct passwd *mm_getpwnamallow(const char *); - char *mm_auth2_read_banner(void); - int mm_auth_password(struct Authctxt *, char *); -diff -up openssh-5.4p1/openbsd-compat/port-linux.c.selinux openssh-5.4p1/openbsd-compat/port-linux.c ---- openssh-5.4p1/openbsd-compat/port-linux.c.selinux 2010-03-01 05:52:50.000000000 +0100 -+++ openssh-5.4p1/openbsd-compat/port-linux.c 2010-03-01 15:22:19.000000000 +0100 -@@ -32,12 +32,17 @@ - #include "log.h" - #include "xmalloc.h" - #include "port-linux.h" -+#include "key.h" -+#include "hostfile.h" -+#include "auth.h" - - #ifdef WITH_SELINUX - #include - #include - #include - -+extern Authctxt *the_authctxt; -+ - /* Wrapper around is_selinux_enabled() to log its return value once only */ - int - ssh_selinux_enabled(void) -@@ -56,23 +61,36 @@ ssh_selinux_enabled(void) - static security_context_t - ssh_selinux_getctxbyname(char *pwname) - { -- security_context_t sc; -- char *sename = NULL, *lvl = NULL; -- int r; -+ security_context_t sc = NULL; -+ char *sename, *lvl; -+ char *role = NULL; -+ int r = 0; - -+ if (the_authctxt) -+ role=the_authctxt->role; - #ifdef HAVE_GETSEUSERBYNAME -- if (getseuserbyname(pwname, &sename, &lvl) != 0) -- return NULL; -+ if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) { -+ sename = NULL; -+ lvl = NULL; -+ } - #else - sename = pwname; - lvl = NULL; - #endif - -+ if (r == 0) { - #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL -- r = get_default_context_with_level(sename, lvl, NULL, &sc); -+ if (role != NULL && role[0]) -+ r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc); -+ else -+ r = get_default_context_with_level(sename, lvl, NULL, &sc); - #else -- r = get_default_context(sename, NULL, &sc); -+ if (role != NULL && role[0]) -+ r = get_default_context_with_role(sename, role, NULL, &sc); -+ else -+ r = get_default_context(sename, NULL, &sc); - #endif -+ } - - if (r != 0) { - switch (security_getenforce()) { diff --git a/openssh-5.6p1-audit.patch b/openssh-5.6p1-audit.patch deleted file mode 100644 index 2232bf1..0000000 --- a/openssh-5.6p1-audit.patch +++ /dev/null @@ -1,276 +0,0 @@ -diff -up openssh-5.6p1/audit-bsm.c.audit openssh-5.6p1/audit-bsm.c ---- openssh-5.6p1/audit-bsm.c.audit 2008-02-25 11:05:04.000000000 +0100 -+++ openssh-5.6p1/audit-bsm.c 2010-10-20 09:15:47.000000000 +0200 -@@ -305,13 +305,13 @@ audit_run_command(const char *command) - } - - void --audit_session_open(const char *ttyn) -+audit_session_open(struct logininfo *li) - { - /* not implemented */ - } - - void --audit_session_close(const char *ttyn) -+audit_session_close(struct logininfo *li) - { - /* not implemented */ - } -diff -up openssh-5.6p1/audit.c.audit openssh-5.6p1/audit.c ---- openssh-5.6p1/audit.c.audit 2006-09-01 07:38:36.000000000 +0200 -+++ openssh-5.6p1/audit.c 2010-10-20 09:15:47.000000000 +0200 -@@ -147,9 +147,9 @@ audit_event(ssh_audit_event_t event) - * within a single connection. - */ - void --audit_session_open(const char *ttyn) -+audit_session_open(struct logininfo *li) - { -- const char *t = ttyn ? ttyn : "(no tty)"; -+ const char *t = li->line ? li->line : "(no tty)"; - - debug("audit session open euid %d user %s tty name %s", geteuid(), - audit_username(), t); -@@ -163,9 +163,9 @@ audit_session_open(const char *ttyn) - * within a single connection. - */ - void --audit_session_close(const char *ttyn) -+audit_session_close(struct logininfo *li) - { -- const char *t = ttyn ? ttyn : "(no tty)"; -+ const char *t = li->line ? li->line : "(no tty)"; - - debug("audit session close euid %d user %s tty name %s", geteuid(), - audit_username(), t); -diff -up openssh-5.6p1/audit.h.audit openssh-5.6p1/audit.h ---- openssh-5.6p1/audit.h.audit 2006-08-05 16:05:10.000000000 +0200 -+++ openssh-5.6p1/audit.h 2010-10-20 09:15:47.000000000 +0200 -@@ -26,6 +26,9 @@ - - #ifndef _SSH_AUDIT_H - # define _SSH_AUDIT_H -+ -+#include "loginrec.h" -+ - enum ssh_audit_event_type { - SSH_LOGIN_EXCEED_MAXTRIES, - SSH_LOGIN_ROOT_DENIED, -@@ -46,8 +49,8 @@ typedef enum ssh_audit_event_type ssh_au - - void audit_connection_from(const char *, int); - void audit_event(ssh_audit_event_t); --void audit_session_open(const char *); --void audit_session_close(const char *); -+void audit_session_open(struct logininfo *); -+void audit_session_close(struct logininfo *); - void audit_run_command(const char *); - ssh_audit_event_t audit_classify_auth(const char *); - -diff -up openssh-5.6p1/audit-linux.c.audit openssh-5.6p1/audit-linux.c ---- openssh-5.6p1/audit-linux.c.audit 2010-10-20 09:15:47.000000000 +0200 -+++ openssh-5.6p1/audit-linux.c 2010-10-20 09:15:47.000000000 +0200 -@@ -0,0 +1,120 @@ -+/* $Id: audit-linux.c,v 1.1 jfch Exp $ */ -+ -+/* -+ * Copyright 2010 Red Hat, Inc. All rights reserved. -+ * Use is subject to license terms. -+ * -+ * 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. -+ * -+ * Red Hat author: Jan F. Chadima -+ */ -+ -+#include "includes.h" -+#if defined(USE_LINUX_AUDIT) -+#include -+#include -+#include -+ -+#include "log.h" -+#include "audit.h" -+#include "canohost.h" -+ -+const char* audit_username(void); -+ -+int -+linux_audit_record_event(int uid, const char *username, -+ const char *hostname, const char *ip, const char *ttyn, int success) -+{ -+ int audit_fd, rc, saved_errno; -+ -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ if (errno == EINVAL || errno == EPROTONOSUPPORT || -+ errno == EAFNOSUPPORT) -+ return 1; /* No audit support in kernel */ -+ else -+ return 0; /* Must prevent login */ -+ } -+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN, -+ NULL, "login", username ? username : "(unknown)", -+ username == NULL ? uid : -1, hostname, ip, ttyn, success); -+ saved_errno = errno; -+ close(audit_fd); -+ errno = saved_errno; -+ return (rc >= 0); -+} -+ -+/* Below is the sshd audit API code */ -+ -+void -+audit_connection_from(const char *host, int port) -+{ -+} -+ /* not implemented */ -+ -+void -+audit_run_command(const char *command) -+{ -+ /* not implemented */ -+} -+ -+void -+audit_session_open(struct logininfo *li) -+{ -+ if (linux_audit_record_event(li->uid, NULL, li->hostname, -+ NULL, li->line, 1) == 0) -+ fatal("linux_audit_write_entry failed: %s", strerror(errno)); -+} -+ -+void -+audit_session_close(struct logininfo *li) -+{ -+ /* not implemented */ -+} -+ -+void -+audit_event(ssh_audit_event_t event) -+{ -+ switch(event) { -+ case SSH_AUTH_SUCCESS: -+ case SSH_CONNECTION_CLOSE: -+ case SSH_NOLOGIN: -+ case SSH_LOGIN_EXCEED_MAXTRIES: -+ case SSH_LOGIN_ROOT_DENIED: -+ break; -+ -+ case SSH_AUTH_FAIL_NONE: -+ case SSH_AUTH_FAIL_PASSWD: -+ case SSH_AUTH_FAIL_KBDINT: -+ case SSH_AUTH_FAIL_PUBKEY: -+ case SSH_AUTH_FAIL_HOSTBASED: -+ case SSH_AUTH_FAIL_GSSAPI: -+ case SSH_INVALID_USER: -+ linux_audit_record_event(-1, audit_username(), NULL, -+ get_remote_ipaddr(), "sshd", 0); -+ break; -+ -+ default: -+ debug("%s: unhandled event %d", __func__, event); -+ } -+} -+ -+#endif /* USE_LINUX_AUDIT */ -diff -up openssh-5.6p1/configure.ac.audit openssh-5.6p1/configure.ac ---- openssh-5.6p1/configure.ac.audit 2010-08-16 05:15:23.000000000 +0200 -+++ openssh-5.6p1/configure.ac 2010-10-20 09:15:47.000000000 +0200 -@@ -1308,7 +1308,7 @@ int main(void) - - AUDIT_MODULE=none - AC_ARG_WITH(audit, -- [ --with-audit=module Enable EXPERIMENTAL audit support (modules=debug,bsm)], -+ [ --with-audit=module Enable audit support (modules=debug,bsm,linux)], - [ - AC_MSG_CHECKING(for supported audit module) - case "$withval" in -@@ -1332,10 +1332,18 @@ AC_ARG_WITH(audit, - AC_CHECK_FUNCS(getaudit_addr aug_get_machine) - AC_DEFINE(USE_BSM_AUDIT, 1, [Use BSM audit module]) - ;; -+ linux) -+ AC_MSG_RESULT(linux) -+ AUDIT_MODULE=linux -+ dnl Checks for headers, libs and functions -+ AC_CHECK_HEADERS(libaudit.h) -+ SSHDLIBS="$SSHDLIBS -laudit" -+ AC_DEFINE(USE_LINUX_AUDIT, 1, [Use Linux audit module]) -+ ;; - debug) - AUDIT_MODULE=debug - AC_MSG_RESULT(debug) -- AC_DEFINE(SSH_AUDIT_EVENTS, 1, Use audit debugging module) -+ AC_DEFINE(SSH_AUDIT_EVENTS, 1, [Use audit debugging module]) - ;; - no) - AC_MSG_RESULT(no) -diff -up openssh-5.6p1/defines.h.audit openssh-5.6p1/defines.h ---- openssh-5.6p1/defines.h.audit 2010-04-09 10:13:27.000000000 +0200 -+++ openssh-5.6p1/defines.h 2010-10-20 09:15:47.000000000 +0200 -@@ -566,6 +566,11 @@ struct winsize { - # define CUSTOM_SSH_AUDIT_EVENTS - #endif - -+#ifdef USE_LINUX_AUDIT -+# define SSH_AUDIT_EVENTS -+# define CUSTOM_SSH_AUDIT_EVENTS -+#endif -+ - #if !defined(HAVE___func__) && defined(HAVE___FUNCTION__) - # define __func__ __FUNCTION__ - #elif !defined(HAVE___func__) -diff -up openssh-5.6p1/loginrec.c.audit openssh-5.6p1/loginrec.c ---- openssh-5.6p1/loginrec.c.audit 2010-04-09 10:13:27.000000000 +0200 -+++ openssh-5.6p1/loginrec.c 2010-10-20 09:15:47.000000000 +0200 -@@ -468,9 +468,9 @@ login_write(struct logininfo *li) - #endif - #ifdef SSH_AUDIT_EVENTS - if (li->type == LTYPE_LOGIN) -- audit_session_open(li->line); -+ audit_session_open(li); - else if (li->type == LTYPE_LOGOUT) -- audit_session_close(li->line); -+ audit_session_close(li); - #endif - return (0); - } -diff -up openssh-5.6p1/Makefile.in.audit openssh-5.6p1/Makefile.in ---- openssh-5.6p1/Makefile.in.audit 2010-05-12 08:51:39.000000000 +0200 -+++ openssh-5.6p1/Makefile.in 2010-10-20 09:15:47.000000000 +0200 -@@ -81,6 +81,7 @@ SSHOBJS= ssh.o readconf.o clientloop.o s - roaming_common.o roaming_client.o - - SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ -+ audit.o audit-bsm.o audit-linux.o platform.o \ - sshpty.o sshlogin.o servconf.o serverloop.o \ - auth.o auth1.o auth2.o auth-options.o session.o \ - auth-chall.o auth2-chall.o groupaccess.o \ -@@ -90,7 +91,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw - auth-krb5.o \ - auth2-gss.o gss-serv.o gss-serv-krb5.o \ - loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \ -- audit.o audit-bsm.o platform.o sftp-server.o sftp-common.o \ -+ sftp-server.o sftp-common.o \ - roaming_common.o roaming_serv.o - - MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out diff --git a/openssh-5.6p1-audit1a.patch b/openssh-5.6p1-audit1a.patch deleted file mode 100644 index bbb1ed2..0000000 --- a/openssh-5.6p1-audit1a.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -up openssh-5.6p1/audit-linux.c.audit1a openssh-5.6p1/audit-linux.c ---- openssh-5.6p1/audit-linux.c.audit1a 2010-12-10 21:47:03.000000000 +0100 -+++ openssh-5.6p1/audit-linux.c 2010-12-10 21:50:31.000000000 +0100 -@@ -59,7 +59,8 @@ linux_audit_record_event(int uid, const - saved_errno = errno; - close(audit_fd); - errno = saved_errno; -- return (rc >= 0); -+ /* do not report error if the error is EPERM and sshd is run as non root user */ -+ return (rc >= 0) || ((rc == -EPERM) && (getuid() != 0)); - } - - /* Below is the sshd audit API code */ diff --git a/openssh-5.6p1-audit2.patch b/openssh-5.6p1-audit2.patch deleted file mode 100644 index 65f5a2b..0000000 --- a/openssh-5.6p1-audit2.patch +++ /dev/null @@ -1,264 +0,0 @@ -diff -up openssh-5.6p1/audit-bsm.c.audit2 openssh-5.6p1/audit-bsm.c ---- openssh-5.6p1/audit-bsm.c.audit2 2010-12-10 21:55:40.000000000 +0100 -+++ openssh-5.6p1/audit-bsm.c 2010-12-10 21:55:41.000000000 +0100 -@@ -316,6 +316,12 @@ audit_session_close(struct logininfo *li - /* not implemented */ - } - -+int -+audit_keyusage(int host_user, const char *type, unsigned len, char *fp, int rv) -+{ -+ /* not implemented */ -+} -+ - void - audit_event(ssh_audit_event_t event) - { -diff -up openssh-5.6p1/audit.c.audit2 openssh-5.6p1/audit.c ---- openssh-5.6p1/audit.c.audit2 2010-12-10 21:55:40.000000000 +0100 -+++ openssh-5.6p1/audit.c 2010-12-10 21:55:41.000000000 +0100 -@@ -111,6 +111,33 @@ audit_event_lookup(ssh_audit_event_t ev) - return(event_lookup[i].name); - } - -+int -+audit_key(int type, int *rv, const Key *key) -+{ -+ char *fp; -+ unsigned size = 0; -+ const char *crypto_name[] = { -+ "ssh-rsa1", -+ "ssh-rsa", -+ "ssh-dsa", -+ "unknown" }; -+ -+ fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); -+ switch(key->type) { -+ case KEY_RSA1: -+ case KEY_RSA: -+ size = RSA_size(key->rsa); -+ break; -+ case KEY_DSA: -+ size = DSA_size(key->dsa); -+ break; -+ } -+ -+ if (audit_keyusage(0, crypto_name[key->type], size, fp, *rv) == 0) -+ *rv = 0; -+ xfree(fp); -+} -+ - # ifndef CUSTOM_SSH_AUDIT_EVENTS - /* - * Null implementations of audit functions. -@@ -182,5 +209,17 @@ audit_run_command(const char *command) - debug("audit run command euid %d user %s command '%.200s'", geteuid(), - audit_username(), command); - } -+ -+/* -+ * This will be called when user is successfully autherized by the RSA1/RSA/DSA key. -+ * -+ * Type is the key type, len is the key length(byte) and fp is the fingerprint of the key. -+ */ -+int -+audit_keyusage(int host_user, const char *type, unsigned len, char *fp, int rv) -+{ -+ debug("audit %s key usage euid %d user %s key type %s key length %d fingerprint %s, result %d", -+ host_user ? "hostbased" : "pubkey", geteuid(), audit_username(), type, len, fp, rv); -+} - # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ - #endif /* SSH_AUDIT_EVENTS */ -diff -up openssh-5.6p1/audit.h.audit2 openssh-5.6p1/audit.h ---- openssh-5.6p1/audit.h.audit2 2010-12-10 21:55:40.000000000 +0100 -+++ openssh-5.6p1/audit.h 2010-12-10 21:55:41.000000000 +0100 -@@ -28,6 +28,7 @@ - # define _SSH_AUDIT_H - - #include "loginrec.h" -+#include "key.h" - - enum ssh_audit_event_type { - SSH_LOGIN_EXCEED_MAXTRIES, -@@ -53,5 +54,7 @@ void audit_session_open(struct logininfo - void audit_session_close(struct logininfo *); - void audit_run_command(const char *); - ssh_audit_event_t audit_classify_auth(const char *); -+int audit_keyusage(int, const char *, unsigned, char *, int); -+int audit_key(int, int *, const Key *); - - #endif /* _SSH_AUDIT_H */ -diff -up openssh-5.6p1/audit-linux.c.audit2 openssh-5.6p1/audit-linux.c ---- openssh-5.6p1/audit-linux.c.audit2 2010-12-10 21:55:41.000000000 +0100 -+++ openssh-5.6p1/audit-linux.c 2010-12-10 22:16:42.000000000 +0100 -@@ -37,6 +37,8 @@ - #include "audit.h" - #include "canohost.h" - -+#define AUDIT_LOG_SIZE 128 -+ - const char* audit_username(void); - - int -@@ -63,6 +65,37 @@ linux_audit_record_event(int uid, const - return (rc >= 0) || ((rc == -EPERM) && (getuid() != 0)); - } - -+int -+audit_keyusage(int host_user, const char *type, unsigned len, char *fp, int rv) -+{ -+ char buf[AUDIT_LOG_SIZE]; -+ int audit_fd, rc, saved_errno; -+ -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ if (errno == EINVAL || errno == EPROTONOSUPPORT || -+ errno == EAFNOSUPPORT) -+ return 1; /* No audit support in kernel */ -+ else -+ return 0; /* Must prevent login */ -+ } -+ snprintf(buf, sizeof(buf), "%s_auth rport=%d", host_user ? "hostbased" : "pubkey", get_remote_port()); -+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL, -+ buf, audit_username(), -1, NULL, get_remote_ipaddr(), NULL, rv); -+ if ((rc < 0) && ((rc != -1) || (getuid() == 0))) -+ goto out; -+ snprintf(buf, sizeof(buf), "key algo=%s size=%d fp=%s rport=%d", -+ type, 8 * len, fp, get_remote_port()); -+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL, -+ buf, audit_username(), -1, NULL, get_remote_ipaddr(), NULL, rv); -+out: -+ saved_errno = errno; -+ audit_close(audit_fd); -+ errno = saved_errno; -+ /* do not report error if the error is EPERM and sshd is run as non root user */ -+ return (rc >= 0) || ((rc == -EPERM) && (getuid() != 0)); -+} -+ - /* Below is the sshd audit API code */ - - void -diff -up openssh-5.6p1/auth2-hostbased.c.audit2 openssh-5.6p1/auth2-hostbased.c ---- openssh-5.6p1/auth2-hostbased.c.audit2 2010-08-05 05:04:50.000000000 +0200 -+++ openssh-5.6p1/auth2-hostbased.c 2010-12-10 21:55:41.000000000 +0100 -@@ -136,6 +136,18 @@ done: - return authenticated; - } - -+int -+hostkey_key_verify(const Key *key, const u_char *sig, u_int slen, const u_char *data, u_int datalen) -+{ -+ int rv; -+ -+ rv = key_verify(key, sig, slen, data, datalen); -+#ifdef SSH_AUDIT_EVENTS -+ audit_key(0, &rv, key); -+#endif -+ return rv; -+} -+ - /* return 1 if given hostkey is allowed */ - int - hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, -diff -up openssh-5.6p1/auth2-pubkey.c.audit2 openssh-5.6p1/auth2-pubkey.c ---- openssh-5.6p1/auth2-pubkey.c.audit2 2010-07-02 05:35:19.000000000 +0200 -+++ openssh-5.6p1/auth2-pubkey.c 2010-12-10 21:55:41.000000000 +0100 -@@ -177,6 +177,18 @@ done: - return authenticated; - } - -+int -+pubkey_key_verify(const Key *key, const u_char *sig, u_int slen, const u_char *data, u_int datalen) -+{ -+ int rv; -+ -+ rv = key_verify(key, sig, slen, data, datalen); -+#ifdef SSH_AUDIT_EVENTS -+ audit_key(1, &rv, key); -+#endif -+ return rv; -+} -+ - static int - match_principals_option(const char *principal_list, struct KeyCert *cert) - { -diff -up openssh-5.6p1/auth.h.audit2 openssh-5.6p1/auth.h ---- openssh-5.6p1/auth.h.audit2 2010-05-10 03:58:03.000000000 +0200 -+++ openssh-5.6p1/auth.h 2010-12-10 21:55:41.000000000 +0100 -@@ -170,6 +170,7 @@ void abandon_challenge_response(Authctxt - char *authorized_keys_file(struct passwd *); - char *authorized_keys_file2(struct passwd *); - char *authorized_principals_file(struct passwd *); -+int pubkey_key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); - - FILE *auth_openkeyfile(const char *, struct passwd *, int); - FILE *auth_openprincipals(const char *, struct passwd *, int); -@@ -185,6 +186,7 @@ Key *get_hostkey_public_by_type(int); - Key *get_hostkey_private_by_type(int); - int get_hostkey_index(Key *); - int ssh1_session_key(BIGNUM *); -+int hostkey_key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); - - /* debug messages during authentication */ - void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); -diff -up openssh-5.6p1/auth-rsa.c.audit2 openssh-5.6p1/auth-rsa.c ---- openssh-5.6p1/auth-rsa.c.audit2 2010-07-16 05:58:37.000000000 +0200 -+++ openssh-5.6p1/auth-rsa.c 2010-12-10 21:55:41.000000000 +0100 -@@ -92,7 +92,10 @@ auth_rsa_verify_response(Key *key, BIGNU - { - u_char buf[32], mdbuf[16]; - MD5_CTX md; -- int len; -+ int len, rv; -+#ifdef SSH_AUDIT_EVENTS -+ char *fp; -+#endif - - if (auth_key_is_revoked(key)) - return 0; -@@ -116,12 +119,18 @@ auth_rsa_verify_response(Key *key, BIGNU - MD5_Final(mdbuf, &md); - - /* Verify that the response is the original challenge. */ -- if (timingsafe_bcmp(response, mdbuf, 16) != 0) { -- /* Wrong answer. */ -- return (0); -+ rv = timingsafe_bcmp(response, mdbuf, 16) == 0; -+ -+#ifdef SSH_AUDIT_EVENTS -+ fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); -+ if (audit_keyusage(1, "ssh-rsa1", RSA_size(key->rsa), fp, rv) == 0) { -+ debug("unsuccessful audit"); -+ rv = 0; - } -- /* Correct answer. */ -- return (1); -+ xfree(fp); -+#endif -+ -+ return rv; - } - - /* -diff -up openssh-5.6p1/monitor.c.audit2 openssh-5.6p1/monitor.c ---- openssh-5.6p1/monitor.c.audit2 2010-08-03 07:50:16.000000000 +0200 -+++ openssh-5.6p1/monitor.c 2010-12-10 21:55:41.000000000 +0100 -@@ -1235,7 +1235,17 @@ mm_answer_keyverify(int sock, Buffer *m) - if (!valid_data) - fatal("%s: bad signature data blob", __func__); - -- verified = key_verify(key, signature, signaturelen, data, datalen); -+ switch (key_blobtype) { -+ case MM_USERKEY: -+ verified = pubkey_key_verify(key, signature, signaturelen, data, datalen); -+ break; -+ case MM_HOSTKEY: -+ verified = hostkey_key_verify(key, signature, signaturelen, data, datalen); -+ break; -+ default: -+ verified = 0; -+ break; -+ } - debug3("%s: key %p signature %s", - __func__, key, (verified == 1) ? "verified" : "unverified"); - diff --git a/openssh-5.6p1-audit3.patch b/openssh-5.6p1-audit3.patch deleted file mode 100644 index a851ba6..0000000 --- a/openssh-5.6p1-audit3.patch +++ /dev/null @@ -1,502 +0,0 @@ -diff -up openssh-5.6p1/audit-bsm.c.audit3 openssh-5.6p1/audit-bsm.c ---- openssh-5.6p1/audit-bsm.c.audit3 2010-12-10 22:17:31.000000000 +0100 -+++ openssh-5.6p1/audit-bsm.c 2010-12-10 22:17:31.000000000 +0100 -@@ -383,4 +383,16 @@ audit_event(ssh_audit_event_t event) - debug("%s: unhandled event %d", __func__, event); - } - } -+ -+void -+audit_unsupported_body(int what) -+{ -+ /* not implemented */ -+} -+ -+void -+audit_kex_body(int ctos, char *enc, char *mac, char *compress) -+{ -+ /* not implemented */ -+} - #endif /* BSM */ -diff -up openssh-5.6p1/audit.c.audit3 openssh-5.6p1/audit.c ---- openssh-5.6p1/audit.c.audit3 2010-12-10 22:17:31.000000000 +0100 -+++ openssh-5.6p1/audit.c 2010-12-10 22:17:31.000000000 +0100 -@@ -36,6 +36,8 @@ - #include "key.h" - #include "hostfile.h" - #include "auth.h" -+#include "ssh-gss.h" -+#include "monitor_wrap.h" - - /* - * Care must be taken when using this since it WILL NOT be initialized when -@@ -138,6 +140,18 @@ audit_key(int type, int *rv, const Key * - xfree(fp); - } - -+void -+audit_unsupported(int what) -+{ -+ PRIVSEP(audit_unsupported_body(what)); -+} -+ -+void -+audit_kex(int ctos, char *enc, char *mac, char *comp) -+{ -+ PRIVSEP(audit_kex_body(ctos, enc, mac, comp)); -+} -+ - # ifndef CUSTOM_SSH_AUDIT_EVENTS - /* - * Null implementations of audit functions. -@@ -221,5 +235,24 @@ audit_keyusage(int host_user, const char - debug("audit %s key usage euid %d user %s key type %s key length %d fingerprint %s, result %d", - host_user ? "hostbased" : "pubkey", geteuid(), audit_username(), type, len, fp, rv); - } -+ -+/* -+ * This will be called when the protocol negotiation fails. -+ */ -+void -+audit_unsupported_body(int what) -+{ -+ debug("audit unsupported protocol ieuid %d type %d", geteuid(), what); -+ -+ -+/* -+ * This will be called on succesfull protocol negotiation. -+ */ -+void -+audit_kex_body(int ctos, char *enc, char *mac, char *compress) -+{ -+ debug("audit procol negotiation euid %d direction %d cipher %s mac %s compresion %s", -+ geteuid(), ctos, enc, mac, compress); -+} - # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ - #endif /* SSH_AUDIT_EVENTS */ -diff -up openssh-5.6p1/audit.h.audit3 openssh-5.6p1/audit.h ---- openssh-5.6p1/audit.h.audit3 2010-12-10 22:17:31.000000000 +0100 -+++ openssh-5.6p1/audit.h 2010-12-10 22:17:31.000000000 +0100 -@@ -56,5 +56,9 @@ void audit_run_command(const char *); - ssh_audit_event_t audit_classify_auth(const char *); - int audit_keyusage(int, const char *, unsigned, char *, int); - int audit_key(int, int *, const Key *); -+void audit_unsupported(int); -+void audit_kex(int, char *, char *, char *); -+void audit_unsupported_body(int); -+void audit_kex_body(int, char *, char *, char *); - - #endif /* _SSH_AUDIT_H */ -diff -up openssh-5.6p1/audit-linux.c.audit3 openssh-5.6p1/audit-linux.c ---- openssh-5.6p1/audit-linux.c.audit3 2010-12-10 22:17:31.000000000 +0100 -+++ openssh-5.6p1/audit-linux.c 2010-12-10 22:20:00.000000000 +0100 -@@ -36,6 +36,8 @@ - #include "log.h" - #include "audit.h" - #include "canohost.h" -+#include "packet.h" -+#include "cipher.h" - - #define AUDIT_LOG_SIZE 128 - -@@ -151,4 +153,54 @@ audit_event(ssh_audit_event_t event) - } - } - -+void -+audit_unsupported_body(int what) -+{ -+#ifdef AUDIT_CRYPTO_SESSION -+ char buf[AUDIT_LOG_SIZE]; -+ const static char *name[] = { "cipher", "mac", "comp" }; -+ int audit_fd, audit_ok; -+ -+ snprintf(buf, sizeof(buf), "unsupported-%s direction=? cipher=? ksize=? rport=%d laddr=%s lport=%d", -+ name[what], get_remote_port(), get_local_ipaddr(packet_get_connection_in()), -+ get_local_port()); -+ audit_fd = audit_open(); -+ if (audit_fd < 0) -+ /* no problem, the next instruction will be fatal() */ -+ return; -+ audit_ok = audit_log_acct_message(audit_fd, AUDIT_CRYPTO_SESSION, NULL, -+ buf, NULL, -1, NULL, get_remote_ipaddr(), NULL, 0); -+ audit_close(audit_fd); -+#endif -+} -+ -+void -+audit_kex_body(int ctos, char *enc, char *mac, char *compress) -+{ -+#ifdef AUDIT_CRYPTO_SESSION -+ char buf[AUDIT_LOG_SIZE]; -+ int audit_fd, audit_ok; -+ const static char *direction[] = { "from-server", "from-client", "both" }; -+ Cipher *cipher = cipher_by_name(enc); -+ -+ snprintf(buf, sizeof(buf), "start direction=%s cipher=%s, ksize=%d rport=%d laddr=%s lport=%d", -+ direction[ctos], enc, cipher ? 8 * cipher->key_len : 0, -+ get_remote_port(), get_local_ipaddr(packet_get_connection_in()), get_local_port()); -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ if (errno == EINVAL || errno == EPROTONOSUPPORT || -+ errno == EAFNOSUPPORT) -+ return; /* No audit support in kernel */ -+ else -+ fatal("cannot open audit"); /* Must prevent login */ -+ } -+ audit_ok = audit_log_acct_message(audit_fd, AUDIT_CRYPTO_SESSION, NULL, -+ buf, NULL, -1, NULL, get_remote_ipaddr(), NULL, 1); -+ audit_close(audit_fd); -+ /* do not abort if the error is EPERM and sshd is run as non root user */ -+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) -+ fatal("cannot write into audit"); /* Must prevent login */ -+#endif -+} -+ - #endif /* USE_LINUX_AUDIT */ -diff -up openssh-5.6p1/auditstub.c.audit3 openssh-5.6p1/auditstub.c ---- openssh-5.6p1/auditstub.c.audit3 2010-12-10 22:17:32.000000000 +0100 -+++ openssh-5.6p1/auditstub.c 2010-12-10 22:17:32.000000000 +0100 -@@ -0,0 +1,39 @@ -+/* $Id: auditstub.c,v 1.1 jfch Exp $ */ -+ -+/* -+ * Copyright 2010 Red Hat, Inc. All rights reserved. -+ * Use is subject to license terms. -+ * -+ * 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. -+ * -+ * Red Hat author: Jan F. Chadima -+ */ -+ -+void -+audit_unsupported(int n) -+{ -+} -+ -+void -+audit_kex(int ctos, char *enc, char *mac, char *comp) -+{ -+} -+ -diff -up openssh-5.6p1/cipher.c.audit3 openssh-5.6p1/cipher.c ---- openssh-5.6p1/cipher.c.audit3 2010-09-03 14:54:23.000000000 +0200 -+++ openssh-5.6p1/cipher.c 2010-12-10 22:17:32.000000000 +0100 -@@ -59,15 +59,7 @@ extern void ssh1_3des_iv(EVP_CIPHER_CTX - extern const EVP_CIPHER *evp_aes_128_ctr(void); - extern void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); - --struct Cipher { -- char *name; -- int number; /* for ssh1 only */ -- u_int block_size; -- u_int key_len; -- u_int discard_len; -- u_int cbc_mode; -- const EVP_CIPHER *(*evptype)(void); --} ciphers[] = { -+struct Cipher ciphers[] = { - { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, EVP_enc_null }, - { "des", SSH_CIPHER_DES, 8, 8, 0, 1, EVP_des_cbc }, - { "3des", SSH_CIPHER_3DES, 8, 16, 0, 1, evp_ssh1_3des }, -diff -up openssh-5.6p1/cipher.h.audit3 openssh-5.6p1/cipher.h ---- openssh-5.6p1/cipher.h.audit3 2009-01-28 06:38:41.000000000 +0100 -+++ openssh-5.6p1/cipher.h 2010-12-10 22:17:32.000000000 +0100 -@@ -61,7 +61,16 @@ - typedef struct Cipher Cipher; - typedef struct CipherContext CipherContext; - --struct Cipher; -+struct Cipher { -+ char *name; -+ int number; /* for ssh1 only */ -+ u_int block_size; -+ u_int key_len; -+ u_int discard_len; -+ u_int cbc_mode; -+ const EVP_CIPHER *(*evptype)(void); -+}; -+ - struct CipherContext { - int plaintext; - EVP_CIPHER_CTX evp; -diff -up openssh-5.6p1/kex.c.audit3 openssh-5.6p1/kex.c ---- openssh-5.6p1/kex.c.audit3 2010-01-08 06:50:41.000000000 +0100 -+++ openssh-5.6p1/kex.c 2010-12-10 22:17:32.000000000 +0100 -@@ -49,6 +49,7 @@ - #include "dispatch.h" - #include "monitor.h" - #include "roaming.h" -+#include "audit.h" - - #if OPENSSL_VERSION_NUMBER >= 0x00907000L - # if defined(HAVE_EVP_SHA256) -@@ -258,9 +259,13 @@ static void - choose_enc(Enc *enc, char *client, char *server) - { - char *name = match_list(client, server, NULL); -- if (name == NULL) -+ if (name == NULL) { -+#ifdef SSH_AUDIT_EVENTS -+ audit_unsupported(0); -+#endif - fatal("no matching cipher found: client %s server %s", - client, server); -+ } - if ((enc->cipher = cipher_by_name(name)) == NULL) - fatal("matching cipher is not supported: %s", name); - enc->name = name; -@@ -275,9 +280,13 @@ static void - choose_mac(Mac *mac, char *client, char *server) - { - char *name = match_list(client, server, NULL); -- if (name == NULL) -+ if (name == NULL) { -+#ifdef SSH_AUDIT_EVENTS -+ audit_unsupported(1); -+#endif - fatal("no matching mac found: client %s server %s", - client, server); -+ } - if (mac_setup(mac, name) < 0) - fatal("unsupported mac %s", name); - /* truncate the key */ -@@ -292,8 +301,12 @@ static void - choose_comp(Comp *comp, char *client, char *server) - { - char *name = match_list(client, server, NULL); -- if (name == NULL) -+ if (name == NULL) { -+#ifdef SSH_AUDIT_EVENTS -+ audit_unsupported(2); -+#endif - fatal("no matching comp found: client %s server %s", client, server); -+ } - if (strcmp(name, "zlib@openssh.com") == 0) { - comp->type = COMP_DELAYED; - } else if (strcmp(name, "zlib") == 0) { -@@ -414,6 +427,9 @@ kex_choose_conf(Kex *kex) - newkeys->enc.name, - newkeys->mac.name, - newkeys->comp.name); -+#ifdef SSH_AUDIT_EVENTS -+ audit_kex(ctos, newkeys->enc.name, newkeys->mac.name, newkeys->comp.name); -+#endif - } - choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); - choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], -diff -up openssh-5.6p1/Makefile.in.audit3 openssh-5.6p1/Makefile.in ---- openssh-5.6p1/Makefile.in.audit3 2010-12-10 22:17:31.000000000 +0100 -+++ openssh-5.6p1/Makefile.in 2010-12-10 22:17:32.000000000 +0100 -@@ -74,7 +74,7 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o b - monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \ - kexgex.o kexdhc.o kexgexc.o msg.o progressmeter.o dns.o \ - entropy.o gss-genr.o umac.o jpake.o schnorr.o \ -- ssh-pkcs11.o -+ ssh-pkcs11.o auditstub.o - - SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ - sshconnect.o sshconnect1.o sshconnect2.o mux.o \ -diff -up openssh-5.6p1/monitor.c.audit3 openssh-5.6p1/monitor.c ---- openssh-5.6p1/monitor.c.audit3 2010-12-10 22:17:31.000000000 +0100 -+++ openssh-5.6p1/monitor.c 2010-12-10 22:17:32.000000000 +0100 -@@ -89,6 +89,7 @@ - #include "ssh2.h" - #include "jpake.h" - #include "roaming.h" -+#include "audit.h" - - #ifdef GSSAPI - static Gssctxt *gsscontext = NULL; -@@ -177,6 +178,8 @@ int mm_answer_gss_checkmic(int, Buffer * - #ifdef SSH_AUDIT_EVENTS - int mm_answer_audit_event(int, Buffer *); - int mm_answer_audit_command(int, Buffer *); -+int mm_answer_audit_unsupported_body(int, Buffer *); -+int mm_answer_audit_kex_body(int, Buffer *); - #endif - - static Authctxt *authctxt; -@@ -225,6 +228,8 @@ struct mon_table mon_dispatch_proto20[] - #endif - #ifdef SSH_AUDIT_EVENTS - {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, -+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, -+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, - #endif - #ifdef BSD_AUTH - {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, -@@ -261,6 +266,8 @@ struct mon_table mon_dispatch_postauth20 - #ifdef SSH_AUDIT_EVENTS - {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, - {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, -+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, -+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, - #endif - {0, 0, NULL} - }; -@@ -292,6 +299,8 @@ struct mon_table mon_dispatch_proto15[] - #endif - #ifdef SSH_AUDIT_EVENTS - {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, -+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, -+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, - #endif - {0, 0, NULL} - }; -@@ -303,6 +312,8 @@ struct mon_table mon_dispatch_postauth15 - #ifdef SSH_AUDIT_EVENTS - {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, - {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, -+ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, -+ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, - #endif - {0, 0, NULL} - }; -@@ -2205,3 +2216,40 @@ mm_answer_jpake_check_confirm(int sock, - } - - #endif /* JPAKE */ -+ -+#ifdef SSH_AUDIT_EVENTS -+int -+mm_answer_audit_unsupported_body(int sock, Buffer *m) -+{ -+ int what; -+ -+ what = buffer_get_int(m); -+ -+ audit_unsupported_body(what); -+ -+ buffer_clear(m); -+ -+ mm_request_send(sock, MONITOR_ANS_AUDIT_UNSUPPORTED, m); -+ return 0; -+} -+ -+int -+mm_answer_audit_kex_body(int sock, Buffer *m) -+{ -+ int ctos, len; -+ char *cipher, *mac, *compress; -+ -+ ctos = buffer_get_int(m); -+ cipher = buffer_get_string(m, &len); -+ mac = buffer_get_string(m, &len); -+ compress = buffer_get_string(m, &len); -+ -+ audit_kex_body(ctos, cipher, mac, compress); -+ -+ buffer_clear(m); -+ -+ mm_request_send(sock, MONITOR_ANS_AUDIT_KEX, m); -+ return 0; -+} -+ -+#endif /* SSH_AUDIT_EVENTS */ -diff -up openssh-5.6p1/monitor.h.audit3 openssh-5.6p1/monitor.h ---- openssh-5.6p1/monitor.h.audit3 2008-11-05 06:20:46.000000000 +0100 -+++ openssh-5.6p1/monitor.h 2010-12-10 22:17:32.000000000 +0100 -@@ -66,6 +66,8 @@ enum monitor_reqtype { - MONITOR_REQ_JPAKE_STEP2, MONITOR_ANS_JPAKE_STEP2, - MONITOR_REQ_JPAKE_KEY_CONFIRM, MONITOR_ANS_JPAKE_KEY_CONFIRM, - MONITOR_REQ_JPAKE_CHECK_CONFIRM, MONITOR_ANS_JPAKE_CHECK_CONFIRM, -+ MONITOR_REQ_AUDIT_UNSUPPORTED, MONITOR_ANS_AUDIT_UNSUPPORTED, -+ MONITOR_REQ_AUDIT_KEX, MONITOR_ANS_AUDIT_KEX, - }; - - struct mm_master; -diff -up openssh-5.6p1/monitor_wrap.c.audit3 openssh-5.6p1/monitor_wrap.c ---- openssh-5.6p1/monitor_wrap.c.audit3 2010-03-07 13:05:17.000000000 +0100 -+++ openssh-5.6p1/monitor_wrap.c 2010-12-10 22:17:32.000000000 +0100 -@@ -1411,3 +1411,38 @@ mm_jpake_check_confirm(const BIGNUM *k, - return success; - } - #endif /* JPAKE */ -+ -+#ifdef SSH_AUDIT_EVENTS -+void -+mm_audit_unsupported_body(int what) -+{ -+ Buffer m; -+ -+ buffer_init(&m); -+ buffer_put_int(&m, what); -+ -+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_UNSUPPORTED, &m); -+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_UNSUPPORTED, -+ &m); -+ -+ buffer_free(&m); -+} -+ -+void -+mm_audit_kex_body(int ctos, char *cipher, char *mac, char *compress) -+{ -+ Buffer m; -+ -+ buffer_init(&m); -+ buffer_put_int(&m, ctos); -+ buffer_put_cstring(&m, cipher); -+ buffer_put_cstring(&m, mac); -+ buffer_put_cstring(&m, compress); -+ -+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_KEX, &m); -+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_KEX, -+ &m); -+ -+ buffer_free(&m); -+} -+#endif /* SSH_AUDIT_EVENTS */ -diff -up openssh-5.6p1/monitor_wrap.h.audit3 openssh-5.6p1/monitor_wrap.h ---- openssh-5.6p1/monitor_wrap.h.audit3 2009-03-05 14:58:22.000000000 +0100 -+++ openssh-5.6p1/monitor_wrap.h 2010-12-10 22:17:32.000000000 +0100 -@@ -74,6 +74,8 @@ void mm_sshpam_free_ctx(void *); - #include "audit.h" - void mm_audit_event(ssh_audit_event_t); - void mm_audit_run_command(const char *); -+void mm_audit_unsupported_body(int); -+void mm_audit_kex_body(int, char *, char *, char *); - #endif - - struct Session; -diff -up openssh-5.6p1/sshd.c.audit3 openssh-5.6p1/sshd.c ---- openssh-5.6p1/sshd.c.audit3 2010-04-16 07:56:22.000000000 +0200 -+++ openssh-5.6p1/sshd.c 2010-12-10 22:17:32.000000000 +0100 -@@ -118,6 +118,7 @@ - #endif - #include "monitor_wrap.h" - #include "roaming.h" -+#include "audit.h" - #include "version.h" - - #ifdef LIBWRAP -@@ -2177,6 +2178,10 @@ do_ssh1_kex(void) - if (cookie[i] != packet_get_char()) - packet_disconnect("IP Spoofing check bytes do not match."); - -+#ifdef SSH_AUDIT_EVENTS -+ audit_kex(2, cipher_name(cipher_type), "crc", "none"); -+#endif -+ - debug("Encryption type: %.200s", cipher_name(cipher_type)); - - /* Get the encrypted integer. */ diff --git a/openssh-5.6p1-audit4.patch b/openssh-5.6p1-audit4.patch deleted file mode 100644 index bbc9783..0000000 --- a/openssh-5.6p1-audit4.patch +++ /dev/null @@ -1,236 +0,0 @@ -diff -up openssh-5.6p1/audit-bsm.c.audit4 openssh-5.6p1/audit-bsm.c ---- openssh-5.6p1/audit-bsm.c.audit4 2011-01-12 14:01:50.000000000 +0100 -+++ openssh-5.6p1/audit-bsm.c 2011-01-12 14:01:51.000000000 +0100 -@@ -395,4 +395,10 @@ audit_kex_body(int ctos, char *enc, char - { - /* not implemented */ - } -+ -+void -+audit_session_key_free_body(int ctos) -+{ -+ /* not implemented */ -+} - #endif /* BSM */ -diff -up openssh-5.6p1/audit.c.audit4 openssh-5.6p1/audit.c ---- openssh-5.6p1/audit.c.audit4 2011-01-12 14:01:50.000000000 +0100 -+++ openssh-5.6p1/audit.c 2011-01-12 14:01:51.000000000 +0100 -@@ -152,6 +152,12 @@ audit_kex(int ctos, char *enc, char *mac - PRIVSEP(audit_kex_body(ctos, enc, mac, comp)); - } - -+void -+audit_session_key_free(int ctos) -+{ -+ PRIVSEP(audit_session_key_free_body(ctos)); -+} -+ - # ifndef CUSTOM_SSH_AUDIT_EVENTS - /* - * Null implementations of audit functions. -@@ -254,5 +260,13 @@ audit_kex_body(int ctos, char *enc, char - debug("audit procol negotiation euid %d direction %d cipher %s mac %s compresion %s", - geteuid(), ctos, enc, mac, compress); - } -+ -+/* -+ * This will be called on succesfull session key discard -+ */ -+audit_session_key_free_body(int ctos) -+{ -+ debug("audit session key discard euid %d direction %d", geteuid(), ctos); -+} - # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ - #endif /* SSH_AUDIT_EVENTS */ -diff -up openssh-5.6p1/audit.h.audit4 openssh-5.6p1/audit.h ---- openssh-5.6p1/audit.h.audit4 2011-01-12 14:01:50.000000000 +0100 -+++ openssh-5.6p1/audit.h 2011-01-12 14:01:51.000000000 +0100 -@@ -60,5 +60,7 @@ void audit_unsupported(int); - void audit_kex(int, char *, char *, char *); - void audit_unsupported_body(int); - void audit_kex_body(int, char *, char *, char *); -+void audit_session_key_free(int ctos); -+void audit_session_key_free_body(int ctos); - - #endif /* _SSH_AUDIT_H */ -diff -up openssh-5.6p1/audit-linux.c.audit4 openssh-5.6p1/audit-linux.c ---- openssh-5.6p1/audit-linux.c.audit4 2011-01-12 14:01:50.000000000 +0100 -+++ openssh-5.6p1/audit-linux.c 2011-01-12 14:04:15.000000000 +0100 -@@ -174,13 +174,14 @@ audit_unsupported_body(int what) - #endif - } - -+const static char *direction[] = { "from-server", "from-client", "both" }; -+ - void - audit_kex_body(int ctos, char *enc, char *mac, char *compress) - { - #ifdef AUDIT_CRYPTO_SESSION - char buf[AUDIT_LOG_SIZE]; - int audit_fd, audit_ok; -- const static char *direction[] = { "from-server", "from-client", "both" }; - Cipher *cipher = cipher_by_name(enc); - - snprintf(buf, sizeof(buf), "start direction=%s cipher=%s, ksize=%d rport=%d laddr=%s lport=%d", -@@ -203,4 +204,26 @@ audit_kex_body(int ctos, char *enc, char - #endif - } - -+void -+audit_session_key_free_body(int ctos) -+{ -+ char buf[AUDIT_LOG_SIZE]; -+ int audit_fd, audit_ok; -+ -+ snprintf(buf, sizeof(buf), "destroy kind=session direction=%s", direction[ctos]); -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ if (errno != EINVAL && errno != EPROTONOSUPPORT && -+ errno != EAFNOSUPPORT) -+ error("cannot open audit"); -+ return; -+ } -+ audit_ok = audit_log_acct_message(audit_fd, AUDIT_CRYPTO_KEY_USER, NULL, -+ buf, NULL, -1, NULL, get_remote_ipaddr(), NULL, 1); -+ audit_close(audit_fd); -+ /* do not abort if the error is EPERM and sshd is run as non root user */ -+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) -+ error("cannot write into audit"); -+} -+ - #endif /* USE_LINUX_AUDIT */ -diff -up openssh-5.6p1/auditstub.c.audit4 openssh-5.6p1/auditstub.c ---- openssh-5.6p1/auditstub.c.audit4 2011-01-12 14:01:50.000000000 +0100 -+++ openssh-5.6p1/auditstub.c 2011-01-12 14:01:51.000000000 +0100 -@@ -37,3 +37,7 @@ audit_kex(int ctos, char *enc, char *mac - { - } - -+void -+audit_session_key_free(int ctos) -+{ -+} -diff -up openssh-5.6p1/monitor.c.audit4 openssh-5.6p1/monitor.c ---- openssh-5.6p1/monitor.c.audit4 2011-01-12 14:01:51.000000000 +0100 -+++ openssh-5.6p1/monitor.c 2011-01-12 14:01:51.000000000 +0100 -@@ -180,6 +180,7 @@ int mm_answer_audit_event(int, Buffer *) - int mm_answer_audit_command(int, Buffer *); - int mm_answer_audit_unsupported_body(int, Buffer *); - int mm_answer_audit_kex_body(int, Buffer *); -+int mm_answer_audit_session_key_free_body(int, Buffer *); - #endif - - static Authctxt *authctxt; -@@ -230,6 +231,7 @@ struct mon_table mon_dispatch_proto20[] - {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, - {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, - {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, -+ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, - #endif - #ifdef BSD_AUTH - {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, -@@ -268,6 +270,7 @@ struct mon_table mon_dispatch_postauth20 - {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, - {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, - {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, -+ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, - #endif - {0, 0, NULL} - }; -@@ -301,6 +304,7 @@ struct mon_table mon_dispatch_proto15[] - {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, - {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, - {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, -+ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, - #endif - {0, 0, NULL} - }; -@@ -314,6 +318,7 @@ struct mon_table mon_dispatch_postauth15 - {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, - {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, - {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, -+ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, - #endif - {0, 0, NULL} - }; -@@ -2252,4 +2257,18 @@ mm_answer_audit_kex_body(int sock, Buffe - return 0; - } - -+int -+mm_answer_audit_session_key_free_body(int sock, Buffer *m) -+{ -+ int ctos; -+ -+ ctos = buffer_get_int(m); -+ -+ audit_session_key_free_body(ctos); -+ -+ buffer_clear(m); -+ -+ mm_request_send(sock, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, m); -+ return 0; -+} - #endif /* SSH_AUDIT_EVENTS */ -diff -up openssh-5.6p1/monitor.h.audit4 openssh-5.6p1/monitor.h ---- openssh-5.6p1/monitor.h.audit4 2011-01-12 14:01:51.000000000 +0100 -+++ openssh-5.6p1/monitor.h 2011-01-12 14:01:51.000000000 +0100 -@@ -68,6 +68,7 @@ enum monitor_reqtype { - MONITOR_REQ_JPAKE_CHECK_CONFIRM, MONITOR_ANS_JPAKE_CHECK_CONFIRM, - MONITOR_REQ_AUDIT_UNSUPPORTED, MONITOR_ANS_AUDIT_UNSUPPORTED, - MONITOR_REQ_AUDIT_KEX, MONITOR_ANS_AUDIT_KEX, -+ MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, - }; - - struct mm_master; -diff -up openssh-5.6p1/monitor_wrap.c.audit4 openssh-5.6p1/monitor_wrap.c ---- openssh-5.6p1/monitor_wrap.c.audit4 2011-01-12 14:01:51.000000000 +0100 -+++ openssh-5.6p1/monitor_wrap.c 2011-01-12 14:01:51.000000000 +0100 -@@ -1445,4 +1445,17 @@ mm_audit_kex_body(int ctos, char *cipher - - buffer_free(&m); - } -+ -+void -+mm_audit_session_key_free_body(int ctos) -+{ -+ Buffer m; -+ -+ buffer_init(&m); -+ buffer_put_int(&m, ctos); -+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SESSION_KEY_FREE, &m); -+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, -+ &m); -+ buffer_free(&m); -+} - #endif /* SSH_AUDIT_EVENTS */ -diff -up openssh-5.6p1/monitor_wrap.h.audit4 openssh-5.6p1/monitor_wrap.h ---- openssh-5.6p1/monitor_wrap.h.audit4 2011-01-12 14:01:51.000000000 +0100 -+++ openssh-5.6p1/monitor_wrap.h 2011-01-12 14:01:51.000000000 +0100 -@@ -76,6 +76,7 @@ void mm_audit_event(ssh_audit_event_t); - void mm_audit_run_command(const char *); - void mm_audit_unsupported_body(int); - void mm_audit_kex_body(int, char *, char *, char *); -+void mm_audit_session_key_free_body(int); - #endif - - struct Session; -diff -up openssh-5.6p1/packet.c.audit4 openssh-5.6p1/packet.c ---- openssh-5.6p1/packet.c.audit4 2010-07-16 05:58:37.000000000 +0200 -+++ openssh-5.6p1/packet.c 2011-01-12 14:01:51.000000000 +0100 -@@ -495,6 +495,7 @@ packet_close(void) - buffer_free(&active_state->compression_buffer); - buffer_compress_uninit(); - } -+ audit_session_key_free(2); - cipher_cleanup(&active_state->send_context); - cipher_cleanup(&active_state->receive_context); - } -@@ -749,6 +750,7 @@ set_newkeys(int mode) - } - if (active_state->newkeys[mode] != NULL) { - debug("set_newkeys: rekeying"); -+ audit_session_key_free(mode); - cipher_cleanup(cc); - enc = &active_state->newkeys[mode]->enc; - mac = &active_state->newkeys[mode]->mac; diff --git a/openssh-5.6p1-audit5.patch b/openssh-5.6p1-audit5.patch deleted file mode 100644 index 4be224a..0000000 --- a/openssh-5.6p1-audit5.patch +++ /dev/null @@ -1,443 +0,0 @@ -diff -up openssh-5.6p1/audit-bsm.c.audit5 openssh-5.6p1/audit-bsm.c ---- openssh-5.6p1/audit-bsm.c.audit5 2011-02-07 18:53:53.000000000 +0100 -+++ openssh-5.6p1/audit-bsm.c 2011-02-07 18:53:53.000000000 +0100 -@@ -401,4 +401,10 @@ audit_session_key_free_body(int ctos) - { - /* not implemented */ - } -+ -+void -+audit_destroy_sensitive_data(void) -+{ -+ /* not implemented */ -+} - #endif /* BSM */ -diff -up openssh-5.6p1/audit.c.audit5 openssh-5.6p1/audit.c ---- openssh-5.6p1/audit.c.audit5 2011-02-07 18:53:53.000000000 +0100 -+++ openssh-5.6p1/audit.c 2011-02-07 18:53:53.000000000 +0100 -@@ -268,5 +268,14 @@ audit_session_key_free_body(int ctos) - { - debug("audit session key discard euid %d direction %d", geteuid(), ctos); - } -+ -+/* -+ * This will be called on destroy private part of the server key -+ */ -+void -+audit_destroy_sensitive_data(void) -+{ -+ debug("audit destroy sensitive data euid %d", geteuid()); -+} - # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ - #endif /* SSH_AUDIT_EVENTS */ -diff -up openssh-5.6p1/audit.h.audit5 openssh-5.6p1/audit.h ---- openssh-5.6p1/audit.h.audit5 2011-02-07 18:53:53.000000000 +0100 -+++ openssh-5.6p1/audit.h 2011-02-07 18:53:53.000000000 +0100 -@@ -62,5 +62,6 @@ void audit_unsupported_body(int); - void audit_kex_body(int, char *, char *, char *); - void audit_session_key_free(int ctos); - void audit_session_key_free_body(int ctos); -+void audit_destroy_sensitive_data(void); - - #endif /* _SSH_AUDIT_H */ -diff -up openssh-5.6p1/audit-linux.c.audit5 openssh-5.6p1/audit-linux.c ---- openssh-5.6p1/audit-linux.c.audit5 2011-02-07 18:53:53.000000000 +0100 -+++ openssh-5.6p1/audit-linux.c 2011-02-07 18:53:53.000000000 +0100 -@@ -226,4 +226,26 @@ audit_session_key_free_body(int ctos) - error("cannot write into audit"); - } - -+void -+audit_destroy_sensitive_data(void) -+{ -+ char buf[AUDIT_LOG_SIZE]; -+ int audit_fd, audit_ok; -+ -+ snprintf(buf, sizeof(buf), "destroy kind=server direction=?"); -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ if (errno != EINVAL && errno != EPROTONOSUPPORT && -+ errno != EAFNOSUPPORT) -+ error("cannot open audit"); -+ return; -+ } -+ audit_ok = audit_log_acct_message(audit_fd, AUDIT_CRYPTO_KEY_USER, NULL, -+ buf, NULL, -1, NULL, get_remote_ipaddr(), NULL, 1); -+ audit_close(audit_fd); -+ /* do not abort if the error is EPERM and sshd is run as non root user */ -+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) -+ error("cannot write into audit"); -+} -+ - #endif /* USE_LINUX_AUDIT */ -diff -up openssh-5.6p1/kex.c.audit5 openssh-5.6p1/kex.c ---- openssh-5.6p1/kex.c.audit5 2011-02-07 18:53:53.000000000 +0100 -+++ openssh-5.6p1/kex.c 2011-02-07 18:53:53.000000000 +0100 -@@ -592,3 +592,34 @@ dump_digest(char *msg, u_char *digest, i - fprintf(stderr, "\n"); - } - #endif -+ -+static void -+enc_destroy(Enc *enc) -+{ -+ if (enc == NULL) -+ return; -+ -+ if (enc->key) { -+ memset(enc->key, 0, enc->key_len); -+ xfree(enc->key); -+ } -+ -+ if (enc->iv) { -+ memset(enc->iv, 0, enc->block_size); -+ xfree(enc->iv); -+ } -+ -+ memset(enc, 0, sizeof(*enc)); -+} -+ -+void -+newkeys_destroy(Newkeys *newkeys) -+{ -+ if (newkeys == NULL) -+ return; -+ -+ enc_destroy(&newkeys->enc); -+ mac_destroy(&newkeys->mac); -+ memset(&newkeys->comp, 0, sizeof(newkeys->comp)); -+} -+ -diff -up openssh-5.6p1/kex.h.audit5 openssh-5.6p1/kex.h ---- openssh-5.6p1/kex.h.audit5 2010-02-26 21:55:05.000000000 +0100 -+++ openssh-5.6p1/kex.h 2011-02-07 18:53:53.000000000 +0100 -@@ -146,6 +146,8 @@ void kexdh_server(Kex *); - void kexgex_client(Kex *); - void kexgex_server(Kex *); - -+void newkeys_destroy(Newkeys *newkeys); -+ - void - kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, - BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *); -diff -up openssh-5.6p1/mac.c.audit5 openssh-5.6p1/mac.c ---- openssh-5.6p1/mac.c.audit5 2008-06-13 02:58:50.000000000 +0200 -+++ openssh-5.6p1/mac.c 2011-02-07 18:53:53.000000000 +0100 -@@ -162,6 +162,20 @@ mac_clear(Mac *mac) - mac->umac_ctx = NULL; - } - -+void -+mac_destroy(Mac *mac) -+{ -+ if (mac == NULL) -+ return; -+ -+ if (mac->key) { -+ memset(mac->key, 0, mac->key_len); -+ xfree(mac->key); -+ } -+ -+ memset(mac, 0, sizeof(*mac)); -+} -+ - /* XXX copied from ciphers_valid */ - #define MAC_SEP "," - int -diff -up openssh-5.6p1/mac.h.audit5 openssh-5.6p1/mac.h ---- openssh-5.6p1/mac.h.audit5 2007-06-11 06:01:42.000000000 +0200 -+++ openssh-5.6p1/mac.h 2011-02-07 18:53:53.000000000 +0100 -@@ -28,3 +28,4 @@ int mac_setup(Mac *, char *); - int mac_init(Mac *); - u_char *mac_compute(Mac *, u_int32_t, u_char *, int); - void mac_clear(Mac *); -+void mac_destroy(Mac *); -diff -up openssh-5.6p1/monitor.c.audit5 openssh-5.6p1/monitor.c ---- openssh-5.6p1/monitor.c.audit5 2011-02-07 18:53:53.000000000 +0100 -+++ openssh-5.6p1/monitor.c 2011-02-07 18:53:53.000000000 +0100 -@@ -181,6 +181,7 @@ int mm_answer_audit_command(int, Buffer - int mm_answer_audit_unsupported_body(int, Buffer *); - int mm_answer_audit_kex_body(int, Buffer *); - int mm_answer_audit_session_key_free_body(int, Buffer *); -+int mm_answer_audit_server_key_free(int, Buffer *); - #endif - - static Authctxt *authctxt; -@@ -232,6 +233,7 @@ struct mon_table mon_dispatch_proto20[] - {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, - {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, - {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, -+ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, - #endif - #ifdef BSD_AUTH - {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, -@@ -271,6 +273,7 @@ struct mon_table mon_dispatch_postauth20 - {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, - {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, - {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, -+ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, - #endif - {0, 0, NULL} - }; -@@ -305,6 +308,7 @@ struct mon_table mon_dispatch_proto15[] - {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, - {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, - {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, -+ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, - #endif - {0, 0, NULL} - }; -@@ -319,6 +323,7 @@ struct mon_table mon_dispatch_postauth15 - {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, - {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, - {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, -+ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, - #endif - {0, 0, NULL} - }; -@@ -2271,4 +2276,15 @@ mm_answer_audit_session_key_free_body(in - mm_request_send(sock, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, m); - return 0; - } -+ -+int -+mm_answer_audit_server_key_free(int sock, Buffer *m) -+{ -+ audit_destroy_sensitive_data(); -+ -+ buffer_clear(m); -+ -+ mm_request_send(sock, MONITOR_ANS_AUDIT_SERVER_KEY_FREE, m); -+ return 0; -+} - #endif /* SSH_AUDIT_EVENTS */ -diff -up openssh-5.6p1/monitor.h.audit5 openssh-5.6p1/monitor.h ---- openssh-5.6p1/monitor.h.audit5 2011-02-07 18:53:53.000000000 +0100 -+++ openssh-5.6p1/monitor.h 2011-02-07 18:53:53.000000000 +0100 -@@ -69,6 +69,7 @@ enum monitor_reqtype { - MONITOR_REQ_AUDIT_UNSUPPORTED, MONITOR_ANS_AUDIT_UNSUPPORTED, - MONITOR_REQ_AUDIT_KEX, MONITOR_ANS_AUDIT_KEX, - MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, -+ MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MONITOR_ANS_AUDIT_SERVER_KEY_FREE, - }; - - struct mm_master; -diff -up openssh-5.6p1/monitor_wrap.c.audit5 openssh-5.6p1/monitor_wrap.c ---- openssh-5.6p1/monitor_wrap.c.audit5 2011-02-07 18:53:53.000000000 +0100 -+++ openssh-5.6p1/monitor_wrap.c 2011-02-07 18:53:53.000000000 +0100 -@@ -1458,4 +1458,16 @@ mm_audit_session_key_free_body(int ctos) - &m); - buffer_free(&m); - } -+ -+void -+mm_audit_destroy_sensitive_data(void) -+{ -+ Buffer m; -+ -+ buffer_init(&m); -+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SERVER_KEY_FREE, &m); -+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_SERVER_KEY_FREE, -+ &m); -+ buffer_free(&m); -+} - #endif /* SSH_AUDIT_EVENTS */ -diff -up openssh-5.6p1/monitor_wrap.h.audit5 openssh-5.6p1/monitor_wrap.h ---- openssh-5.6p1/monitor_wrap.h.audit5 2011-02-07 18:53:53.000000000 +0100 -+++ openssh-5.6p1/monitor_wrap.h 2011-02-07 18:53:53.000000000 +0100 -@@ -77,6 +77,7 @@ void mm_audit_run_command(const char *); - void mm_audit_unsupported_body(int); - void mm_audit_kex_body(int, char *, char *, char *); - void mm_audit_session_key_free_body(int); -+void mm_audit_server_key_free_body(void); - #endif - - struct Session; -diff -up openssh-5.6p1/packet.c.audit5 openssh-5.6p1/packet.c ---- openssh-5.6p1/packet.c.audit5 2011-02-07 18:53:53.000000000 +0100 -+++ openssh-5.6p1/packet.c 2011-02-07 18:53:54.000000000 +0100 -@@ -60,6 +60,7 @@ - #include - - #include "xmalloc.h" -+#include "audit.h" - #include "buffer.h" - #include "packet.h" - #include "crc32.h" -@@ -495,9 +496,9 @@ packet_close(void) - buffer_free(&active_state->compression_buffer); - buffer_compress_uninit(); - } -- audit_session_key_free(2); - cipher_cleanup(&active_state->send_context); - cipher_cleanup(&active_state->receive_context); -+ audit_session_key_free(2); - } - - /* Sets remote side protocol flags. */ -@@ -1893,6 +1894,34 @@ packet_get_newkeys(int mode) - return (void *)active_state->newkeys[mode]; - } - -+static void -+packet_destroy_state(struct session_state *state) -+{ -+ if (state == NULL) -+ return; -+ -+ cipher_cleanup(&state->receive_context); -+ cipher_cleanup(&state->send_context); -+ -+ buffer_free(&state->input); -+ buffer_free(&state->output); -+ buffer_free(&state->outgoing_packet); -+ buffer_free(&state->incoming_packet); -+ buffer_free(&state->compression_buffer); -+ newkeys_destroy(state->newkeys[MODE_IN]); -+ newkeys_destroy(state->newkeys[MODE_OUT]); -+ mac_destroy(state->packet_discard_mac); -+// TAILQ_HEAD(, packet) outgoing; -+// memset(state, 0, sizeof(state)); -+} -+ -+void -+packet_destroy_all(void) -+{ -+ packet_destroy_state(active_state); -+ packet_destroy_state(backup_state); -+} -+ - /* - * Save the state for the real connection, and use a separate state when - * resuming a suspended connection. -@@ -1900,18 +1929,12 @@ packet_get_newkeys(int mode) - void - packet_backup_state(void) - { -- struct session_state *tmp; -- - close(active_state->connection_in); - active_state->connection_in = -1; - close(active_state->connection_out); - active_state->connection_out = -1; -- if (backup_state) -- tmp = backup_state; -- else -- tmp = alloc_session_state(); - backup_state = active_state; -- active_state = tmp; -+ active_state = alloc_session_state(); - } - - /* -@@ -1928,9 +1951,7 @@ packet_restore_state(void) - backup_state = active_state; - active_state = tmp; - active_state->connection_in = backup_state->connection_in; -- backup_state->connection_in = -1; - active_state->connection_out = backup_state->connection_out; -- backup_state->connection_out = -1; - len = buffer_len(&backup_state->input); - if (len > 0) { - buf = buffer_ptr(&backup_state->input); -@@ -1938,4 +1959,10 @@ packet_restore_state(void) - buffer_clear(&backup_state->input); - add_recv_bytes(len); - } -+ backup_state->connection_in = -1; -+ backup_state->connection_out = -1; -+ packet_destroy_state(backup_state); -+ xfree(backup_state); -+ backup_state = NULL; - } -+ -diff -up openssh-5.6p1/packet.h.audit5 openssh-5.6p1/packet.h ---- openssh-5.6p1/packet.h.audit5 2009-07-05 23:11:13.000000000 +0200 -+++ openssh-5.6p1/packet.h 2011-02-07 18:53:54.000000000 +0100 -@@ -115,4 +115,5 @@ void packet_restore_state(void); - void *packet_get_input(void); - void *packet_get_output(void); - -+void packet_destroy_all(void); - #endif /* PACKET_H */ -diff -up openssh-5.6p1/session.c.audit5 openssh-5.6p1/session.c ---- openssh-5.6p1/session.c.audit5 2010-06-26 02:00:15.000000000 +0200 -+++ openssh-5.6p1/session.c 2011-02-07 18:53:54.000000000 +0100 -@@ -1677,6 +1677,7 @@ do_child(Session *s, const char *command - - /* remove hostkey from the child's memory */ - destroy_sensitive_data(); -+ PRIVSEP(audit_destroy_sensitive_data()); - - /* Force a password change */ - if (s->authctxt->force_pwchange) { -diff -up openssh-5.6p1/sshd.c.audit5 openssh-5.6p1/sshd.c ---- openssh-5.6p1/sshd.c.audit5 2011-02-07 18:53:53.000000000 +0100 -+++ openssh-5.6p1/sshd.c 2011-02-07 19:08:56.000000000 +0100 -@@ -579,6 +579,7 @@ demote_sensitive_data(void) - } - /* Certs do not need demotion */ - } -+ audit_destroy_sensitive_data(); - - /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */ - } -@@ -663,6 +664,8 @@ privsep_preauth(Authctxt *authctxt) - return (0); - } - -+extern Newkeys *current_keys[]; -+ - static void - privsep_postauth(Authctxt *authctxt) - { -@@ -688,6 +691,10 @@ privsep_postauth(Authctxt *authctxt) - verbose("User child is on pid %ld", (long)pmonitor->m_pid); - close(pmonitor->m_recvfd); - buffer_clear(&loginmsg); -+ newkeys_destroy(current_keys[MODE_OUT]); -+ newkeys_destroy(current_keys[MODE_IN]); -+ packet_destroy_all(); -+ audit_session_key_free_body(2); - monitor_child_postauth(pmonitor); - - /* NEVERREACHED */ -@@ -1970,6 +1977,8 @@ main(int ac, char **av) - */ - if (use_privsep) { - mm_send_keystate(pmonitor); -+ packet_destroy_all(); -+ audit_session_key_free(2); - exit(0); - } - -@@ -2011,8 +2020,10 @@ main(int ac, char **av) - if (use_privsep) { - privsep_postauth(authctxt); - /* the monitor process [priv] will not return */ -- if (!compat20) -+ if (!compat20) { - destroy_sensitive_data(); -+ audit_destroy_sensitive_data(); -+ } - } - - packet_set_timeout(options.client_alive_interval, -@@ -2022,6 +2033,9 @@ main(int ac, char **av) - do_authenticated(authctxt); - - /* The connection has been terminated. */ -+ packet_destroy_all(); -+ audit_session_key_free(2); -+ - packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes); - packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes); - verbose("Transferred: sent %llu, received %llu bytes", obytes, ibytes); -@@ -2249,6 +2263,7 @@ do_ssh1_kex(void) - } - /* Destroy the private and public keys. No longer. */ - destroy_sensitive_data(); -+ audit_destroy_sensitive_data(); - - if (use_privsep) - mm_ssh1_session_id(session_id); diff --git a/openssh-5.6p1-authorized-keys-command.patch b/openssh-5.6p1-authorized-keys-command.patch deleted file mode 100644 index 3075f34..0000000 --- a/openssh-5.6p1-authorized-keys-command.patch +++ /dev/null @@ -1,447 +0,0 @@ -diff -up openssh-5.6p1/auth2-pubkey.c.akc openssh-5.6p1/auth2-pubkey.c ---- openssh-5.6p1/auth2-pubkey.c.akc 2010-09-03 15:24:51.000000000 +0200 -+++ openssh-5.6p1/auth2-pubkey.c 2010-09-03 15:24:51.000000000 +0200 -@@ -27,6 +27,7 @@ - - #include - #include -+#include - - #include - #include -@@ -264,27 +265,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); - -@@ -377,8 +366,6 @@ user_key_allowed2(struct passwd *pw, Key - break; - } - } -- restore_uid(); -- fclose(f); - key_free(found); - if (!found_key) - debug2("key not found"); -@@ -440,13 +427,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 -1; -+ -+ /* 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.6p1/configure.ac.akc openssh-5.6p1/configure.ac ---- openssh-5.6p1/configure.ac.akc 2010-09-03 15:24:51.000000000 +0200 -+++ openssh-5.6p1/configure.ac 2010-09-03 15:24:51.000000000 +0200 -@@ -1346,6 +1346,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 \ -@@ -4209,6 +4221,7 @@ echo " Linux audit 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.6p1/servconf.c.akc openssh-5.6p1/servconf.c ---- openssh-5.6p1/servconf.c.akc 2010-09-03 15:24:50.000000000 +0200 -+++ openssh-5.6p1/servconf.c 2010-09-03 15:24:51.000000000 +0200 -@@ -129,6 +129,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; -@@ -316,6 +318,7 @@ typedef enum { - sUsePrivilegeSeparation, sAllowAgentForwarding, - sZeroKnowledgePasswordAuthentication, sHostCertificate, - sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, -+ sAuthorizedKeysCommand, sAuthorizedKeysCommandRunAs, - sDeprecated, sUnsupported - } ServerOpCodes; - -@@ -439,6 +442,13 @@ static struct { - { "revokedkeys", sRevokedKeys, SSHCFG_ALL }, - { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, - { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, 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 } - }; - -@@ -1360,6 +1370,20 @@ process_server_config_line(ServerOptions - charptr = &options->revoked_keys_file; - goto parse_filename; - -+ 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 (*activep && *charptr == NULL) -+ *charptr = xstrdup(arg); -+ break; -+ - case sDeprecated: - logit("%s line %d: Deprecated option %s", - filename, linenum, arg); -@@ -1453,6 +1477,8 @@ copy_set_server_options(ServerOptions *d - M_CP_INTOPT(gss_authentication); - M_CP_INTOPT(rsa_authentication); - M_CP_INTOPT(pubkey_authentication); -+ M_CP_STROPT(authorized_keys_command); -+ M_CP_STROPT(authorized_keys_command_runas); - M_CP_INTOPT(kerberos_authentication); - M_CP_INTOPT(hostbased_authentication); - M_CP_INTOPT(hostbased_uses_name_from_packet_only); -@@ -1705,6 +1731,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.6p1/servconf.h.akc openssh-5.6p1/servconf.h ---- openssh-5.6p1/servconf.h.akc 2010-09-03 15:24:50.000000000 +0200 -+++ openssh-5.6p1/servconf.h 2010-09-03 15:24:51.000000000 +0200 -@@ -158,6 +158,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; - - void initialize_server_options(ServerOptions *); -diff -up openssh-5.6p1/sshd_config.0.akc openssh-5.6p1/sshd_config.0 ---- openssh-5.6p1/sshd_config.0.akc 2010-09-03 15:24:50.000000000 +0200 -+++ openssh-5.6p1/sshd_config.0 2010-09-03 15:27:26.000000000 +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 -@@ -375,7 +392,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.6p1/sshd_config.5.akc openssh-5.6p1/sshd_config.5 ---- openssh-5.6p1/sshd_config.5.akc 2010-09-03 15:24:50.000000000 +0200 -+++ openssh-5.6p1/sshd_config.5 2010-09-03 15:24:51.000000000 +0200 -@@ -654,6 +654,8 @@ Available keywords are - .Cm AllowAgentForwarding , - .Cm AllowTcpForwarding , - .Cm AuthorizedKeysFile , -+.Cm AuthorizedKeysCommand , -+.Cm AuthorizedKeysCommandRunAs , - .Cm AuthorizedPrincipalsFile , - .Cm Banner , - .Cm ChrootDirectory , -@@ -666,6 +668,7 @@ Available keywords are - .Cm KerberosAuthentication , - .Cm MaxAuthTries , - .Cm MaxSessions , -+.Cm PubkeyAuthentication , - .Cm PasswordAuthentication , - .Cm PermitEmptyPasswords , - .Cm PermitOpen , -@@ -868,6 +871,20 @@ 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 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. -+.Dq - .It Cm RhostsRSAAuthentication - Specifies whether rhosts or /etc/hosts.equiv authentication together - with successful RSA host authentication is allowed. -diff -up openssh-5.6p1/sshd_config.akc openssh-5.6p1/sshd_config ---- openssh-5.6p1/sshd_config.akc 2010-09-03 15:24:50.000000000 +0200 -+++ openssh-5.6p1/sshd_config 2010-09-03 15:24:51.000000000 +0200 -@@ -45,6 +45,8 @@ SyslogFacility AUTHPRIV - #RSAAuthentication yes - #PubkeyAuthentication yes - #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 diff --git a/openssh-5.6p1-biguid.patch b/openssh-5.6p1-biguid.patch deleted file mode 100644 index 5892008..0000000 --- a/openssh-5.6p1-biguid.patch +++ /dev/null @@ -1,99 +0,0 @@ -diff -up openssh-5.6p1/loginrec.c.biguid openssh-5.6p1/loginrec.c ---- openssh-5.6p1/loginrec.c.biguid 2010-11-15 13:19:35.000000000 +0100 -+++ openssh-5.6p1/loginrec.c 2010-11-15 13:19:38.000000000 +0100 -@@ -273,7 +273,7 @@ login_logout(struct logininfo *li) - * try to retrieve lastlog information from wtmp/wtmpx. - */ - unsigned int --login_get_lastlog_time(const int uid) -+login_get_lastlog_time(const uid_t uid) - { - struct logininfo li; - -@@ -297,7 +297,7 @@ login_get_lastlog_time(const int uid) - * 0 on failure (will use OpenSSH's logging facilities for diagnostics) - */ - struct logininfo * --login_get_lastlog(struct logininfo *li, const int uid) -+login_get_lastlog(struct logininfo *li, const uid_t uid) - { - struct passwd *pw; - -@@ -311,7 +311,8 @@ login_get_lastlog(struct logininfo *li, - */ - pw = getpwuid(uid); - if (pw == NULL) -- fatal("%s: Cannot find account for uid %i", __func__, uid); -+ fatal("%s: Cannot find account for uid %ld", __func__, -+ (long)uid); - - /* No MIN_SIZEOF here - we absolutely *must not* truncate the - * username (XXX - so check for trunc!) */ -@@ -335,7 +336,7 @@ login_get_lastlog(struct logininfo *li, - * allocation fails, the program halts. - */ - struct --logininfo *login_alloc_entry(int pid, const char *username, -+logininfo *login_alloc_entry(pid_t pid, const char *username, - const char *hostname, const char *line) - { - struct logininfo *newli; -@@ -363,7 +364,7 @@ login_free_entry(struct logininfo *li) - * Returns: 1 - */ - int --login_init_entry(struct logininfo *li, int pid, const char *username, -+login_init_entry(struct logininfo *li, pid_t pid, const char *username, - const char *hostname, const char *line) - { - struct passwd *pw; -@@ -1496,7 +1497,7 @@ lastlog_openseek(struct logininfo *li, i - - if (S_ISREG(st.st_mode)) { - /* find this uid's offset in the lastlog file */ -- offset = (off_t) ((long)li->uid * sizeof(struct lastlog)); -+ offset = (off_t) ((u_long)li->uid * sizeof(struct lastlog)); - - if (lseek(*fd, offset, SEEK_SET) != offset) { - logit("%s: %s->lseek(): %s", __func__, -diff -up openssh-5.6p1/loginrec.h.biguid openssh-5.6p1/loginrec.h ---- openssh-5.6p1/loginrec.h.biguid 2010-06-22 07:02:39.000000000 +0200 -+++ openssh-5.6p1/loginrec.h 2010-11-15 13:19:38.000000000 +0100 -@@ -63,8 +63,8 @@ struct logininfo { - char progname[LINFO_PROGSIZE]; /* name of program (for PAM) */ - int progname_null; - short int type; /* type of login (LTYPE_*) */ -- int pid; /* PID of login process */ -- int uid; /* UID of this user */ -+ pid_t pid; /* PID of login process */ -+ uid_t uid; /* UID of this user */ - char line[LINFO_LINESIZE]; /* tty/pty name */ - char username[LINFO_NAMESIZE]; /* login username */ - char hostname[LINFO_HOSTSIZE]; /* remote hostname */ -@@ -86,12 +86,12 @@ struct logininfo { - /** 'public' functions */ - - /* construct a new login entry */ --struct logininfo *login_alloc_entry(int pid, const char *username, -+struct logininfo *login_alloc_entry(pid_t pid, const char *username, - const char *hostname, const char *line); - /* free a structure */ - void login_free_entry(struct logininfo *li); - /* fill out a pre-allocated structure with useful information */ --int login_init_entry(struct logininfo *li, int pid, const char *username, -+int login_init_entry(struct logininfo *li, pid_t pid, const char *username, - const char *hostname, const char *line); - /* place the current time in a logininfo struct */ - void login_set_current_time(struct logininfo *li); -@@ -117,9 +117,9 @@ void login_set_addr(struct logininfo *li - * lastlog retrieval functions - */ - /* lastlog *entry* functions fill out a logininfo */ --struct logininfo *login_get_lastlog(struct logininfo *li, const int uid); -+struct logininfo *login_get_lastlog(struct logininfo *li, const uid_t uid); - /* lastlog *time* functions return time_t equivalent (uint) */ --unsigned int login_get_lastlog_time(const int uid); -+unsigned int login_get_lastlog_time(const uid_t uid); - - /* produce various forms of the line filename */ - char *line_fullname(char *dst, const char *src, u_int dstsize); diff --git a/openssh-5.6p1-clientloop.patch b/openssh-5.6p1-clientloop.patch deleted file mode 100644 index 7ccb1e3..0000000 --- a/openssh-5.6p1-clientloop.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up openssh-5.6p1/clientloop.c.clientloop openssh-5.6p1/clientloop.c ---- openssh-5.6p1/clientloop.c.clientloop 2010-11-24 08:18:10.000000000 +0100 -+++ openssh-5.6p1/clientloop.c 2010-11-24 08:18:11.000000000 +0100 -@@ -1944,7 +1944,7 @@ client_input_channel_req(int type, u_int - } - packet_check_eom(); - } -- if (reply) { -+ if (reply && c != NULL) { - packet_start(success ? - SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); - packet_put_int(c->remote_id); diff --git a/openssh-5.6p1-fips.patch b/openssh-5.6p1-fips.patch deleted file mode 100644 index 41cb742..0000000 --- a/openssh-5.6p1-fips.patch +++ /dev/null @@ -1,710 +0,0 @@ -diff -up openssh-5.6p1/audit.c.fips openssh-5.6p1/audit.c ---- openssh-5.6p1/audit.c.fips 2011-01-16 23:45:01.000000000 +0100 -+++ openssh-5.6p1/audit.c 2011-01-16 23:45:59.000000000 +0100 -@@ -124,7 +124,7 @@ audit_key(int type, int *rv, const Key * - "ssh-dsa", - "unknown" }; - -- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); -+ fp = key_fingerprint(key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); - switch(key->type) { - case KEY_RSA1: - case KEY_RSA: -diff -up openssh-5.6p1/auth2-pubkey.c.fips openssh-5.6p1/auth2-pubkey.c ---- openssh-5.6p1/auth2-pubkey.c.fips 2011-01-16 23:41:58.000000000 +0100 -+++ openssh-5.6p1/auth2-pubkey.c 2011-01-16 23:41:59.000000000 +0100 -@@ -36,6 +36,7 @@ - #include - #include - #include -+#include - - #include "xmalloc.h" - #include "ssh.h" -@@ -371,7 +372,7 @@ user_search_key_in_file(FILE *f, char *f - found_key = 1; - debug("matching key found: file %s, line %lu", - file, linenum); -- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); -+ fp = key_fingerprint(found, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); - verbose("Found matching %s key: %s", - key_type(found), fp); - xfree(fp); -diff -up openssh-5.6p1/authfile.c.fips openssh-5.6p1/authfile.c ---- openssh-5.6p1/authfile.c.fips 2010-08-05 05:05:16.000000000 +0200 -+++ openssh-5.6p1/authfile.c 2011-01-16 23:41:59.000000000 +0100 -@@ -146,8 +146,14 @@ key_save_private_rsa1(Key *key, const ch - /* Allocate space for the private part of the key in the buffer. */ - cp = buffer_append_space(&encrypted, buffer_len(&buffer)); - -- cipher_set_key_string(&ciphercontext, cipher, passphrase, -- CIPHER_ENCRYPT); -+ if (cipher_set_key_string(&ciphercontext, cipher, passphrase, -+ CIPHER_ENCRYPT) < 0) { -+ error("cipher_set_key_string failed."); -+ buffer_free(&encrypted); -+ buffer_free(&buffer); -+ return 0; -+ } -+ - cipher_crypt(&ciphercontext, cp, - buffer_ptr(&buffer), buffer_len(&buffer)); - cipher_cleanup(&ciphercontext); -@@ -421,8 +427,14 @@ key_load_private_rsa1(int fd, const char - cp = buffer_append_space(&decrypted, buffer_len(&buffer)); - - /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ -- cipher_set_key_string(&ciphercontext, cipher, passphrase, -- CIPHER_DECRYPT); -+ if (cipher_set_key_string(&ciphercontext, cipher, passphrase, -+ CIPHER_DECRYPT) < 0) { -+ error("cipher_set_key_string failed."); -+ buffer_free(&decrypted); -+ buffer_free(&buffer); -+ goto fail; -+ } -+ - cipher_crypt(&ciphercontext, cp, - buffer_ptr(&buffer), buffer_len(&buffer)); - cipher_cleanup(&ciphercontext); -diff -up openssh-5.6p1/auth-rsa.c.fips openssh-5.6p1/auth-rsa.c ---- openssh-5.6p1/auth-rsa.c.fips 2011-01-16 23:46:11.000000000 +0100 -+++ openssh-5.6p1/auth-rsa.c 2011-01-16 23:46:31.000000000 +0100 -@@ -122,7 +122,7 @@ auth_rsa_verify_response(Key *key, BIGNU - rv = timingsafe_bcmp(response, mdbuf, 16) == 0; - - #ifdef SSH_AUDIT_EVENTS -- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); -+ fp = key_fingerprint(key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); - if (audit_keyusage(1, "ssh-rsa1", RSA_size(key->rsa), fp, rv) == 0) { - debug("unsuccessful audit"); - rv = 0; -diff -up openssh-5.6p1/cipher.c.fips openssh-5.6p1/cipher.c ---- openssh-5.6p1/cipher.c.fips 2011-01-16 23:41:56.000000000 +0100 -+++ openssh-5.6p1/cipher.c 2011-01-16 23:41:59.000000000 +0100 -@@ -40,6 +40,7 @@ - #include - - #include -+#include - - #include - #include -@@ -85,6 +86,22 @@ struct Cipher ciphers[] = { - { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL } - }; - -+struct Cipher fips_ciphers[] = { -+ { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, EVP_enc_null }, -+ { "3des", SSH_CIPHER_3DES, 8, 16, 0, 1, evp_ssh1_3des }, -+ -+ { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 1, EVP_des_ede3_cbc }, -+ { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 1, EVP_aes_128_cbc }, -+ { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 1, EVP_aes_192_cbc }, -+ { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc }, -+ { "rijndael-cbc@lysator.liu.se", -+ SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc }, -+ { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, evp_aes_128_ctr }, -+ { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, evp_aes_128_ctr }, -+ { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, evp_aes_128_ctr }, -+ { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL } -+}; -+ - /*--*/ - - u_int -@@ -127,7 +144,7 @@ Cipher * - cipher_by_name(const char *name) - { - Cipher *c; -- for (c = ciphers; c->name != NULL; c++) -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) - if (strcmp(c->name, name) == 0) - return c; - return NULL; -@@ -137,7 +154,7 @@ Cipher * - cipher_by_number(int id) - { - Cipher *c; -- for (c = ciphers; c->name != NULL; c++) -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) - if (c->number == id) - return c; - return NULL; -@@ -181,7 +198,7 @@ cipher_number(const char *name) - Cipher *c; - if (name == NULL) - return -1; -- for (c = ciphers; c->name != NULL; c++) -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) - if (strcasecmp(c->name, name) == 0) - return c->number; - return -1; -@@ -288,14 +305,15 @@ cipher_cleanup(CipherContext *cc) - * passphrase and using the resulting 16 bytes as the key. - */ - --void -+int - cipher_set_key_string(CipherContext *cc, Cipher *cipher, - const char *passphrase, int do_encrypt) - { - MD5_CTX md; - u_char digest[16]; - -- MD5_Init(&md); -+ if (MD5_Init(&md) <= 0) -+ return -1; - MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase)); - MD5_Final(digest, &md); - -@@ -303,6 +321,7 @@ cipher_set_key_string(CipherContext *cc, - - memset(digest, 0, sizeof(digest)); - memset(&md, 0, sizeof(md)); -+ return 0; - } - - /* -diff -up openssh-5.6p1/cipher-ctr.c.fips openssh-5.6p1/cipher-ctr.c ---- openssh-5.6p1/cipher-ctr.c.fips 2007-06-14 15:21:33.000000000 +0200 -+++ openssh-5.6p1/cipher-ctr.c 2011-01-16 23:41:59.000000000 +0100 -@@ -140,7 +140,8 @@ evp_aes_128_ctr(void) - aes_ctr.do_cipher = ssh_aes_ctr; - #ifndef SSH_OLD_EVP - aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | -- EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; -+ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV | -+ EVP_CIPH_FLAG_FIPS; - #endif - return (&aes_ctr); - } -diff -up openssh-5.6p1/cipher.h.fips openssh-5.6p1/cipher.h ---- openssh-5.6p1/cipher.h.fips 2011-01-16 23:41:56.000000000 +0100 -+++ openssh-5.6p1/cipher.h 2011-01-16 23:41:59.000000000 +0100 -@@ -87,7 +87,7 @@ void cipher_init(CipherContext *, Ciphe - const u_char *, u_int, int); - void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int); - void cipher_cleanup(CipherContext *); --void cipher_set_key_string(CipherContext *, Cipher *, const char *, int); -+int cipher_set_key_string(CipherContext *, Cipher *, const char *, int); - u_int cipher_blocksize(const Cipher *); - u_int cipher_keylen(const Cipher *); - u_int cipher_is_cbc(const Cipher *); -diff -up openssh-5.6p1/mac.c.fips openssh-5.6p1/mac.c ---- openssh-5.6p1/mac.c.fips 2008-06-13 02:58:50.000000000 +0200 -+++ openssh-5.6p1/mac.c 2011-01-16 23:41:59.000000000 +0100 -@@ -28,6 +28,7 @@ - #include - - #include -+#include - - #include - #include -@@ -47,14 +48,14 @@ - #define SSH_EVP 1 /* OpenSSL EVP-based MAC */ - #define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */ - --struct { -+struct Macs { - char *name; - int type; - const EVP_MD * (*mdfunc)(void); - int truncatebits; /* truncate digest if != 0 */ - int key_len; /* just for UMAC */ - int len; /* just for UMAC */ --} macs[] = { -+} all_macs[] = { - { "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1, -1 }, - { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, -1, -1 }, - { "hmac-md5", SSH_EVP, EVP_md5, 0, -1, -1 }, -@@ -65,9 +66,15 @@ struct { - { NULL, 0, NULL, 0, -1, -1 } - }; - -+struct Macs fips_macs[] = { -+ { "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1, -1 }, -+ { NULL, 0, NULL, 0, -1, -1 } -+}; -+ - static void - mac_setup_by_id(Mac *mac, int which) - { -+ struct Macs *macs = FIPS_mode() ? fips_macs : all_macs; - int evp_len; - mac->type = macs[which].type; - if (mac->type == SSH_EVP) { -@@ -88,6 +95,7 @@ int - mac_setup(Mac *mac, char *name) - { - int i; -+ struct Macs *macs = FIPS_mode() ? fips_macs : all_macs; - - for (i = 0; macs[i].name; i++) { - if (strcmp(name, macs[i].name) == 0) { -diff -up openssh-5.6p1/Makefile.in.fips openssh-5.6p1/Makefile.in ---- openssh-5.6p1/Makefile.in.fips 2011-01-16 23:41:58.000000000 +0100 -+++ openssh-5.6p1/Makefile.in 2011-01-16 23:41:59.000000000 +0100 -@@ -142,25 +142,25 @@ libssh.a: $(LIBSSH_OBJS) - $(RANLIB) $@ - - ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) -- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) -- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) -+ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHDLIBS) $(LIBS) - - scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o - $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) - - ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o -- $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o -- $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o -- $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o roaming_dummy.o readconf.o -- $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o - $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) -@@ -169,7 +169,7 @@ ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) l - $(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o -- $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) -+ $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS) - - sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o - $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -diff -up openssh-5.6p1/myproposal.h.fips openssh-5.6p1/myproposal.h ---- openssh-5.6p1/myproposal.h.fips 2010-04-16 07:56:22.000000000 +0200 -+++ openssh-5.6p1/myproposal.h 2011-01-16 23:41:59.000000000 +0100 -@@ -58,7 +58,12 @@ - "hmac-sha1-96,hmac-md5-96" - #define KEX_DEFAULT_COMP "none,zlib@openssh.com,zlib" - #define KEX_DEFAULT_LANG "" -- -+#define KEX_FIPS_ENCRYPT \ -+ "aes128-ctr,aes192-ctr,aes256-ctr," \ -+ "aes128-cbc,3des-cbc," \ -+ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se" -+#define KEX_FIPS_MAC \ -+ "hmac-sha1" - - static char *myproposal[PROPOSAL_MAX] = { - KEX_DEFAULT_KEX, -diff -up openssh-5.6p1/openbsd-compat/bsd-arc4random.c.fips openssh-5.6p1/openbsd-compat/bsd-arc4random.c ---- openssh-5.6p1/openbsd-compat/bsd-arc4random.c.fips 2010-03-25 22:52:02.000000000 +0100 -+++ openssh-5.6p1/openbsd-compat/bsd-arc4random.c 2011-01-16 23:41:59.000000000 +0100 -@@ -39,6 +39,7 @@ - static int rc4_ready = 0; - static RC4_KEY rc4; - -+#if 0 - unsigned int - arc4random(void) - { -@@ -82,6 +83,32 @@ arc4random_stir(void) - - rc4_ready = REKEY_BYTES; - } -+#else -+unsigned int -+arc4random(void) -+{ -+ unsigned int r = 0; -+ void *rp = &r; -+ -+ if (!rc4_ready) { -+ arc4random_stir(); -+ } -+ RAND_bytes(rp, sizeof(r)); -+ -+ return(r); -+} -+ -+void -+arc4random_stir(void) -+{ -+ unsigned char rand_buf[SEED_SIZE]; -+ -+ if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) -+ fatal("Couldn't obtain random bytes (error %ld)", -+ ERR_get_error()); -+ rc4_ready = 1; -+} -+#endif - #endif /* !HAVE_ARC4RANDOM */ - - #ifndef HAVE_ARC4RANDOM_BUF -diff -up openssh-5.6p1/ssh-add.c.fips openssh-5.6p1/ssh-add.c ---- openssh-5.6p1/ssh-add.c.fips 2010-05-21 06:56:47.000000000 +0200 -+++ openssh-5.6p1/ssh-add.c 2011-01-16 23:41:59.000000000 +0100 -@@ -42,6 +42,7 @@ - #include - - #include -+#include - #include "openbsd-compat/openssl-compat.h" - - #include -@@ -277,7 +278,7 @@ list_identities(AuthenticationConnection - key = ssh_get_next_identity(ac, &comment, version)) { - had_identities = 1; - if (do_fp) { -- fp = key_fingerprint(key, SSH_FP_MD5, -+ fp = key_fingerprint(key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, - SSH_FP_HEX); - printf("%d %s %s (%s)\n", - key_size(key), fp, comment, key_type(key)); -diff -up openssh-5.6p1/ssh-agent.c.fips openssh-5.6p1/ssh-agent.c ---- openssh-5.6p1/ssh-agent.c.fips 2010-04-16 07:56:22.000000000 +0200 -+++ openssh-5.6p1/ssh-agent.c 2011-01-16 23:41:59.000000000 +0100 -@@ -51,6 +51,7 @@ - - #include - #include -+#include - #include "openbsd-compat/openssl-compat.h" - - #include -@@ -199,9 +200,9 @@ confirm_key(Identity *id) - char *p; - int ret = -1; - -- p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); -- if (ask_permission("Allow use of key %s?\nKey fingerprint %s.", -- id->comment, p)) -+ p = key_fingerprint(id->key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); -+ if (ask_permission("Allow use of key %s?\nKey %sfingerprint %s.", -+ id->comment, FIPS_mode() ? "SHA1 " : "", p)) - ret = 0; - xfree(p); - -diff -up openssh-5.6p1/ssh.c.fips openssh-5.6p1/ssh.c ---- openssh-5.6p1/ssh.c.fips 2010-08-16 17:59:31.000000000 +0200 -+++ openssh-5.6p1/ssh.c 2011-01-16 23:41:59.000000000 +0100 -@@ -72,6 +72,8 @@ - - #include - #include -+#include -+#include - #include "openbsd-compat/openssl-compat.h" - #include "openbsd-compat/sys-queue.h" - -@@ -235,6 +237,10 @@ main(int ac, char **av) - sanitise_stdfd(); - - __progname = ssh_get_progname(av[0]); -+ SSLeay_add_all_algorithms(); -+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) { -+ fatal("FIPS integrity verification test failed."); -+ } - init_rng(); - - /* -@@ -301,6 +307,9 @@ main(int ac, char **av) - "ACD:F:I:KL:MNO:PR:S:TVw:W:XYy")) != -1) { - switch (opt) { - case '1': -+ if (FIPS_mode()) { -+ fatal("Protocol 1 not allowed in the FIPS mode."); -+ } - options.protocol = SSH_PROTO_1; - break; - case '2': -@@ -599,7 +608,6 @@ main(int ac, char **av) - if (!host) - usage(); - -- SSLeay_add_all_algorithms(); - ERR_load_crypto_strings(); - - /* Initialize the command to execute on remote host. */ -@@ -685,6 +693,10 @@ main(int ac, char **av) - - seed_rng(); - -+ if (FIPS_mode()) { -+ logit("FIPS mode initialized"); -+ } -+ - if (options.user == NULL) - options.user = xstrdup(pw->pw_name); - -@@ -752,6 +764,12 @@ main(int ac, char **av) - - timeout_ms = options.connection_timeout * 1000; - -+ if (FIPS_mode()) { -+ options.protocol &= SSH_PROTO_2; -+ if (options.protocol == 0) -+ fatal("Protocol 2 disabled by configuration but required in the FIPS mode."); -+ } -+ - /* Open a connection to the remote host. */ - if (ssh_connect(host, &hostaddr, options.port, - options.address_family, options.connection_attempts, &timeout_ms, -diff -up openssh-5.6p1/sshconnect2.c.fips openssh-5.6p1/sshconnect2.c ---- openssh-5.6p1/sshconnect2.c.fips 2011-01-16 23:41:59.000000000 +0100 -+++ openssh-5.6p1/sshconnect2.c 2011-01-16 23:41:59.000000000 +0100 -@@ -44,6 +44,8 @@ - #include - #endif - -+#include -+ - #include "openbsd-compat/sys-queue.h" - - #include "xmalloc.h" -@@ -116,6 +118,10 @@ ssh_kex2(char *host, struct sockaddr *ho - if (options.ciphers != NULL) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; -+ } else if (FIPS_mode()) { -+ myproposal[PROPOSAL_ENC_ALGS_CTOS] = -+ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT; -+ - } - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); -@@ -131,7 +137,11 @@ ssh_kex2(char *host, struct sockaddr *ho - if (options.macs != NULL) { - myproposal[PROPOSAL_MAC_ALGS_CTOS] = - myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; -+ } else if (FIPS_mode()) { -+ myproposal[PROPOSAL_MAC_ALGS_CTOS] = -+ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC; - } -+ - if (options.hostkeyalgorithms != NULL) - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = - options.hostkeyalgorithms; -@@ -529,8 +539,8 @@ input_userauth_pk_ok(int type, u_int32_t - key->type, pktype); - goto done; - } -- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); -- debug2("input_userauth_pk_ok: fp %s", fp); -+ fp = key_fingerprint(key, SSH_FP_SHA1, SSH_FP_HEX); -+ debug2("input_userauth_pk_ok: SHA1 fp %s", fp); - xfree(fp); - - /* -diff -up openssh-5.6p1/sshconnect.c.fips openssh-5.6p1/sshconnect.c ---- openssh-5.6p1/sshconnect.c.fips 2010-04-18 00:08:21.000000000 +0200 -+++ openssh-5.6p1/sshconnect.c 2011-01-16 23:41:59.000000000 +0100 -@@ -40,6 +40,8 @@ - #include - #include - -+#include -+ - #include "xmalloc.h" - #include "key.h" - #include "hostfile.h" -@@ -789,6 +791,7 @@ check_host_key(char *hostname, struct so - goto fail; - } else if (options.strict_host_key_checking == 2) { - char msg1[1024], msg2[1024]; -+ int fips_on = FIPS_mode(); - - if (show_other_keys(host, host_key)) - snprintf(msg1, sizeof(msg1), -@@ -797,8 +800,8 @@ check_host_key(char *hostname, struct so - else - snprintf(msg1, sizeof(msg1), "."); - /* The default */ -- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); -- ra = key_fingerprint(host_key, SSH_FP_MD5, -+ fp = key_fingerprint(host_key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); -+ ra = key_fingerprint(host_key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, - SSH_FP_RANDOMART); - msg2[0] = '\0'; - if (options.verify_host_key_dns) { -@@ -814,10 +817,10 @@ check_host_key(char *hostname, struct so - snprintf(msg, sizeof(msg), - "The authenticity of host '%.200s (%s)' can't be " - "established%s\n" -- "%s key fingerprint is %s.%s%s\n%s" -+ "%s key %sfingerprint is %s.%s%s\n%s" - "Are you sure you want to continue connecting " - "(yes/no)? ", -- host, ip, msg1, type, fp, -+ host, ip, msg1, type, fips_on ? "SHA1 " : "", fp, - options.visual_host_key ? "\n" : "", - options.visual_host_key ? ra : "", - msg2); -@@ -1151,17 +1154,18 @@ show_key_from_file(const char *file, con - Key *found; - char *fp, *ra; - int line, ret; -+ int fips_on = FIPS_mode(); - - found = key_new(keytype); - if ((ret = lookup_key_in_hostfile_by_type(file, host, - keytype, found, &line))) { -- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); -- ra = key_fingerprint(found, SSH_FP_MD5, SSH_FP_RANDOMART); -+ fp = key_fingerprint(found, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); -+ ra = key_fingerprint(found, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_RANDOMART); - logit("WARNING: %s key found for host %s\n" - "in %s:%d\n" -- "%s key fingerprint %s.\n%s\n", -+ "%s key %sfingerprint %s.\n%s\n", - key_type(found), host, file, line, -- key_type(found), fp, ra); -+ key_type(found), fips_on ? "SHA1 ":"", fp, ra); - xfree(ra); - xfree(fp); - } -@@ -1207,8 +1211,9 @@ warn_changed_key(Key *host_key) - { - char *fp; - const char *type = key_type(host_key); -+ int fips_on = FIPS_mode(); - -- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); -+ fp = key_fingerprint(host_key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); - - error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); - error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); -@@ -1216,8 +1221,8 @@ warn_changed_key(Key *host_key) - error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"); - error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!"); - error("It is also possible that the %s host key has just been changed.", type); -- error("The fingerprint for the %s key sent by the remote host is\n%s.", -- type, fp); -+ error("The %sfingerprint for the %s key sent by the remote host is\n%s.", -+ fips_on ? "SHA1 ":"", type, fp); - error("Please contact your system administrator."); - - xfree(fp); -diff -up openssh-5.6p1/sshd.c.fips openssh-5.6p1/sshd.c ---- openssh-5.6p1/sshd.c.fips 2011-01-16 23:41:58.000000000 +0100 -+++ openssh-5.6p1/sshd.c 2011-01-16 23:41:59.000000000 +0100 -@@ -76,6 +76,8 @@ - #include - #include - #include -+#include -+#include - #include "openbsd-compat/openssl-compat.h" - - #ifdef HAVE_SECUREWARE -@@ -1309,6 +1311,12 @@ main(int ac, char **av) - (void)set_auth_parameters(ac, av); - #endif - __progname = ssh_get_progname(av[0]); -+ -+ SSLeay_add_all_algorithms(); -+ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) { -+ fatal("FIPS integrity verification test failed."); -+ } -+ - init_rng(); - - /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ -@@ -1470,8 +1478,6 @@ main(int ac, char **av) - else - closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); - -- SSLeay_add_all_algorithms(); -- - /* - * Force logging to stderr until we have loaded the private host - * key (unless started from inetd) -@@ -1589,6 +1595,10 @@ main(int ac, char **av) - debug("private host key: #%d type %d %s", i, key->type, - key_type(key)); - } -+ if ((options.protocol & SSH_PROTO_1) && FIPS_mode()) { -+ logit("Disabling protocol version 1. Not allowed in the FIPS mode."); -+ options.protocol &= ~SSH_PROTO_1; -+ } - if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { - logit("Disabling protocol version 1. Could not load host key"); - options.protocol &= ~SSH_PROTO_1; -@@ -1753,6 +1763,10 @@ main(int ac, char **av) - /* Initialize the random number generator. */ - arc4random_stir(); - -+ if (FIPS_mode()) { -+ logit("FIPS mode initialized"); -+ } -+ - /* Chdir to the root directory so that the current disk can be - unmounted if desired. */ - chdir("/"); -@@ -2293,6 +2307,9 @@ do_ssh2_kex(void) - if (options.ciphers != NULL) { - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; -+ } else if (FIPS_mode()) { -+ myproposal[PROPOSAL_ENC_ALGS_CTOS] = -+ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT; - } - myproposal[PROPOSAL_ENC_ALGS_CTOS] = - compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); -@@ -2302,6 +2319,9 @@ do_ssh2_kex(void) - if (options.macs != NULL) { - myproposal[PROPOSAL_MAC_ALGS_CTOS] = - myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; -+ } else if (FIPS_mode()) { -+ myproposal[PROPOSAL_MAC_ALGS_CTOS] = -+ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC; - } - if (options.compression == COMP_NONE) { - myproposal[PROPOSAL_COMP_ALGS_CTOS] = -diff -up openssh-5.6p1/ssh-keygen.c.fips openssh-5.6p1/ssh-keygen.c ---- openssh-5.6p1/ssh-keygen.c.fips 2011-01-16 23:41:58.000000000 +0100 -+++ openssh-5.6p1/ssh-keygen.c 2011-01-16 23:41:59.000000000 +0100 -@@ -21,6 +21,7 @@ - - #include - #include -+#include - #include "openbsd-compat/openssl-compat.h" - - #include -@@ -692,7 +693,7 @@ do_fingerprint(struct passwd *pw) - enum fp_type fptype; - struct stat st; - -- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; -+ fptype = print_bubblebabble ? SSH_FP_SHA1 : FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5; - rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; - - if (!have_identity) -@@ -2209,14 +2210,15 @@ passphrase_again: - fclose(f); - - if (!quiet) { -- char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX); -- char *ra = key_fingerprint(public, SSH_FP_MD5, -+ int fips_on = FIPS_mode(); -+ char *fp = key_fingerprint(public, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); -+ char *ra = key_fingerprint(public, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, - SSH_FP_RANDOMART); - printf("Your public key has been saved in %s.\n", - identity_file); -- printf("The key fingerprint is:\n"); -+ printf("The key %sfingerprint is:\n", fips_on ? "SHA1 " : ""); - printf("%s %s\n", fp, comment); -- printf("The key's randomart image is:\n"); -+ printf("The key's %srandomart image is:\n", fips_on ? "SHA1 " :""); - printf("%s\n", ra); - xfree(ra); - xfree(fp); diff --git a/openssh-5.6p1-gsskex.patch b/openssh-5.6p1-gsskex.patch deleted file mode 100644 index 53211b0..0000000 --- a/openssh-5.6p1-gsskex.patch +++ /dev/null @@ -1,2937 +0,0 @@ -diff -up openssh-5.6p1/auth2.c.gsskex openssh-5.6p1/auth2.c ---- openssh-5.6p1/auth2.c.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/auth2.c 2011-01-24 23:51:08.000000000 +0100 -@@ -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 -@@ -289,6 +291,7 @@ input_userauth_request(int type, u_int32 - #endif - - authctxt->postponed = 0; -+ authctxt->server_caused_failure = 0; - - /* try to authenticate user */ - m = authmethod_lookup(method); -@@ -361,7 +364,8 @@ userauth_finish(Authctxt *authctxt, int - } else { - - /* Allow initial try of "none" auth without failure penalty */ -- if (authctxt->attempt > 1 || strcmp(method, "none") != 0) -+ if (!authctxt->server_caused_failure && -+ (authctxt->attempt > 1 || strcmp(method, "none") != 0)) - authctxt->failures++; - if (authctxt->failures >= options.max_authtries) { - #ifdef SSH_AUDIT_EVENTS -diff -up openssh-5.6p1/auth2-gss.c.gsskex openssh-5.6p1/auth2-gss.c ---- openssh-5.6p1/auth2-gss.c.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/auth2-gss.c 2011-01-24 23:51:08.000000000 +0100 -@@ -1,7 +1,7 @@ - /* $OpenBSD: auth2-gss.c,v 1.16 2007/10/29 00:52:45 dtucker 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 -@@ -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) -@@ -102,6 +136,7 @@ userauth_gssapi(Authctxt *authctxt) - - if (!present) { - xfree(doid); -+ authctxt->server_caused_failure = 1; - return (0); - } - -@@ -109,6 +144,7 @@ userauth_gssapi(Authctxt *authctxt) - if (ctxt != NULL) - ssh_gssapi_delete_ctx(&ctxt); - xfree(doid); -+ authctxt->server_caused_failure = 1; - return (0); - } - -@@ -242,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); -@@ -284,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"); - -@@ -301,6 +339,12 @@ input_gssapi_mic(int type, u_int32_t ple - userauth_finish(authctxt, authenticated, "gssapi-with-mic"); - } - -+Authmethod method_gsskeyex = { -+ "gssapi-keyex", -+ userauth_gsskeyex, -+ &options.gss_authentication -+}; -+ - Authmethod method_gssapi = { - "gssapi-with-mic", - userauth_gssapi, -diff -up openssh-5.6p1/auth.h.gsskex openssh-5.6p1/auth.h ---- openssh-5.6p1/auth.h.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/auth.h 2011-01-24 23:51:08.000000000 +0100 -@@ -53,6 +53,7 @@ struct Authctxt { - int valid; /* user exists and is allowed to login */ - int attempt; - int failures; -+ int server_caused_failure; - int force_pwchange; - char *user; /* username sent by the client */ - char *service; -diff -up openssh-5.6p1/auth-krb5.c.gsskex openssh-5.6p1/auth-krb5.c ---- openssh-5.6p1/auth-krb5.c.gsskex 2009-12-21 00:49:22.000000000 +0100 -+++ openssh-5.6p1/auth-krb5.c 2011-01-24 23:51:08.000000000 +0100 -@@ -170,8 +170,13 @@ auth_krb5_password(Authctxt *authctxt, c - - len = strlen(authctxt->krb5_ticket_file) + 6; - authctxt->krb5_ccname = xmalloc(len); -+#ifdef USE_CCAPI -+ snprintf(authctxt->krb5_ccname, len, "API:%s", -+ authctxt->krb5_ticket_file); -+#else - snprintf(authctxt->krb5_ccname, len, "FILE:%s", - authctxt->krb5_ticket_file); -+#endif - - #ifdef USE_PAM - if (options.use_pam) -@@ -226,15 +231,22 @@ 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[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX"; -+ int tmpfd; -+#endif - - ret = snprintf(ccname, sizeof(ccname), -- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); -+ cctemplate, geteuid()); - if (ret < 0 || (size_t)ret >= sizeof(ccname)) - return ENOMEM; - -+#ifndef USE_CCAPI - old_umask = umask(0177); - tmpfd = mkstemp(ccname + strlen("FILE:")); - umask(old_umask); -@@ -249,6 +261,7 @@ ssh_krb5_cc_gen(krb5_context ctx, krb5_c - return errno; - } - close(tmpfd); -+#endif - - return (krb5_cc_resolve(ctx, ccname, ccache)); - } -diff -up openssh-5.6p1/ChangeLog.gssapi.gsskex openssh-5.6p1/ChangeLog.gssapi ---- openssh-5.6p1/ChangeLog.gssapi.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/ChangeLog.gssapi 2011-01-24 23:51:08.000000000 +0100 -@@ -0,0 +1,95 @@ -+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-5.6p1/clientloop.c.gsskex openssh-5.6p1/clientloop.c ---- openssh-5.6p1/clientloop.c.gsskex 2010-08-03 08:04:46.000000000 +0200 -+++ openssh-5.6p1/clientloop.c 2011-01-24 23:51:08.000000000 +0100 -@@ -111,6 +111,10 @@ - #include "msg.h" - #include "roaming.h" - -+#ifdef GSSAPI -+#include "ssh-gss.h" -+#endif -+ - /* import options */ - extern Options options; - -@@ -1483,6 +1487,13 @@ client_loop(int have_pty, int escape_cha - /* Do channel operations unless rekeying in progress. */ - if (!rekeying) { - channel_after_select(readset, writeset); -+ -+ if (options.gss_renewal_rekey && -+ ssh_gssapi_credentials_updated(GSS_C_NO_CONTEXT)) { -+ debug("credentials updated - forcing rekey"); -+ need_rekeying = 1; -+ } -+ - if (need_rekeying || packet_need_rekeying()) { - debug("need rekeying"); - xxx_kex->done = 0; -diff -up openssh-5.6p1/configure.ac.gsskex openssh-5.6p1/configure.ac ---- openssh-5.6p1/configure.ac.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/configure.ac 2011-01-24 23:51:09.000000000 +0100 -@@ -477,6 +477,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-5.6p1/gss-genr.c.gsskex openssh-5.6p1/gss-genr.c ---- openssh-5.6p1/gss-genr.c.gsskex 2009-06-22 08:11:07.000000000 +0200 -+++ openssh-5.6p1/gss-genr.c 2011-01-24 23:51:09.000000000 +0100 -@@ -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-5.6p1/gss-serv.c.gsskex openssh-5.6p1/gss-serv.c ---- openssh-5.6p1/gss-serv.c.gsskex 2008-05-19 07:05:07.000000000 +0200 -+++ openssh-5.6p1/gss-serv.c 2011-01-24 23:51:09.000000000 +0100 -@@ -1,7 +1,7 @@ - /* $OpenBSD: gss-serv.c,v 1.22 2008/05/08 12:02:23 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 -@@ -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, -@@ -247,8 +284,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); -+ } -+ -+ ctx->major = gss_compare_name(&ctx->minor, client->name, -+ new_name, &equal); - -- gss_buffer_desc ename; -+ 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; - -@@ -263,6 +340,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); -@@ -280,6 +364,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; -@@ -327,7 +413,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; - -@@ -337,9 +423,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); -@@ -352,14 +440,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-5.6p1/gss-serv-krb5.c.gsskex openssh-5.6p1/gss-serv-krb5.c ---- openssh-5.6p1/gss-serv-krb5.c.gsskex 2006-09-01 07:38:36.000000000 +0200 -+++ openssh-5.6p1/gss-serv-krb5.c 2011-01-24 23:51:09.000000000 +0100 -@@ -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,16 @@ 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, "FILE:%s", new_ccname); -+ client->store.filename = xstrdup(new_ccname); -+#endif - - #ifdef USE_PAM - if (options.use_pam) -@@ -184,6 +190,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 +262,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-5.6p1/kex.c.gsskex openssh-5.6p1/kex.c ---- openssh-5.6p1/kex.c.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/kex.c 2011-01-24 23:51:09.000000000 +0100 -@@ -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 -@@ -339,6 +343,20 @@ choose_kex(Kex *k, char *client, char *s - k->kex_type = KEX_DH_GEX_SHA256; - k->evp_md = evp_ssh_sha256(); - #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-5.6p1/kexgssc.c.gsskex openssh-5.6p1/kexgssc.c ---- openssh-5.6p1/kexgssc.c.gsskex 2011-01-24 23:51:09.000000000 +0100 -+++ openssh-5.6p1/kexgssc.c 2011-01-24 23:51:09.000000000 +0100 -@@ -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 (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-5.6p1/kexgsss.c.gsskex openssh-5.6p1/kexgsss.c ---- openssh-5.6p1/kexgsss.c.gsskex 2011-01-24 23:51:09.000000000 +0100 -+++ openssh-5.6p1/kexgsss.c 2011-01-24 23:51:09.000000000 +0100 -@@ -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 (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-5.6p1/kex.h.gsskex openssh-5.6p1/kex.h ---- openssh-5.6p1/kex.h.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/kex.h 2011-01-24 23:52:26.000000000 +0100 -@@ -67,6 +67,9 @@ enum kex_exchange { - KEX_DH_GRP14_SHA1, - KEX_DH_GEX_SHA1, - KEX_DH_GEX_SHA256, -+ KEX_GSS_GRP1_SHA1, -+ KEX_GSS_GRP14_SHA1, -+ KEX_GSS_GEX_SHA1, - KEX_MAX - }; - -@@ -123,6 +126,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 *); -@@ -148,6 +157,11 @@ void kexgex_server(Kex *); - - void newkeys_destroy(Newkeys *newkeys); - -+#ifdef GSSAPI -+void kexgss_client(Kex *); -+void kexgss_server(Kex *); -+#endif -+ - void - kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, - BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *); -diff -up openssh-5.6p1/key.c.gsskex openssh-5.6p1/key.c ---- openssh-5.6p1/key.c.gsskex 2010-07-16 05:58:37.000000000 +0200 -+++ openssh-5.6p1/key.c 2011-01-24 23:51:09.000000000 +0100 -@@ -1020,6 +1020,8 @@ key_type_from_name(char *name) - return KEY_RSA_CERT; - } else if (strcmp(name, "ssh-dss-cert-v01@openssh.com") == 0) { - return KEY_DSA_CERT; -+ } else if (strcmp(name, "null") == 0) { -+ return KEY_NULL; - } - debug2("key_type_from_name: unknown key type '%s'", name); - return KEY_UNSPEC; -diff -up openssh-5.6p1/key.h.gsskex openssh-5.6p1/key.h ---- openssh-5.6p1/key.h.gsskex 2010-04-16 07:56:22.000000000 +0200 -+++ openssh-5.6p1/key.h 2011-01-24 23:51:09.000000000 +0100 -@@ -39,6 +39,7 @@ enum types { - KEY_DSA_CERT, - KEY_RSA_CERT_V00, - KEY_DSA_CERT_V00, -+ KEY_NULL, - KEY_UNSPEC - }; - enum fp_type { -diff -up openssh-5.6p1/Makefile.in.gsskex openssh-5.6p1/Makefile.in ---- openssh-5.6p1/Makefile.in.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/Makefile.in 2011-01-24 23:51:09.000000000 +0100 -@@ -77,11 +77,11 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o b - monitor_fdpass.o rijndael.o ssh-dss.o ssh-rsa.o dh.o kexdh.o \ - kexgex.o kexdhc.o kexgexc.o msg.o progressmeter.o dns.o \ - entropy.o gss-genr.o umac.o jpake.o schnorr.o \ -- ssh-pkcs11.o auditstub.o -+ ssh-pkcs11.o auditstub.o kexgssc.o - - SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ - sshconnect.o sshconnect1.o sshconnect2.o mux.o \ -- roaming_common.o roaming_client.o -+ roaming_common.o roaming_client.o kexgssc.o - - SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ - audit.o audit-bsm.o audit-linux.o platform.o \ -@@ -95,7 +95,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw - auth2-gss.o gss-serv.o gss-serv-krb5.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 -+ roaming_common.o roaming_serv.o kexgsss.o - - MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-ldap-helper.8.out sshd_config.5.out ssh_config.5.out ssh-ldap.conf.5.out - MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-ldap-helper.8 sshd_config.5 ssh_config.5 ssh-ldap.conf.5 -diff -up openssh-5.6p1/monitor.c.gsskex openssh-5.6p1/monitor.c ---- openssh-5.6p1/monitor.c.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/monitor.c 2011-01-24 23:51:09.000000000 +0100 -@@ -176,6 +176,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 -@@ -256,6 +258,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}, -@@ -268,6 +271,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}, -@@ -384,6 +393,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; - -@@ -470,6 +483,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); -@@ -1754,6 +1771,13 @@ mm_get_kex(Buffer *m) - kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; - kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; - kex->kex[KEX_DH_GEX_SHA256] = kexgex_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); -@@ -1960,6 +1984,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; - -@@ -1987,6 +2014,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); -@@ -2004,6 +2034,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); - } -@@ -2015,6 +2046,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); -@@ -2041,7 +2075,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); -@@ -2054,6 +2092,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-5.6p1/monitor.h.gsskex openssh-5.6p1/monitor.h ---- openssh-5.6p1/monitor.h.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/monitor.h 2011-01-24 23:51:09.000000000 +0100 -@@ -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-5.6p1/monitor_wrap.c.gsskex openssh-5.6p1/monitor_wrap.c ---- openssh-5.6p1/monitor_wrap.c.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/monitor_wrap.c 2011-01-24 23:51:09.000000000 +0100 -@@ -1250,7 +1250,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; -@@ -1267,6 +1267,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-5.6p1/monitor_wrap.h.gsskex openssh-5.6p1/monitor_wrap.h ---- openssh-5.6p1/monitor_wrap.h.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/monitor_wrap.h 2011-01-24 23:51:09.000000000 +0100 -@@ -60,8 +60,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-5.6p1/readconf.c.gsskex openssh-5.6p1/readconf.c ---- openssh-5.6p1/readconf.c.gsskex 2010-08-03 08:04:46.000000000 +0200 -+++ openssh-5.6p1/readconf.c 2011-01-24 23:51:09.000000000 +0100 -@@ -127,6 +127,7 @@ typedef enum { - oClearAllForwardings, oNoHostAuthenticationForLocalhost, - oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, - oAddressFamily, oGssAuthentication, oGssDelegateCreds, -+ oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey, - oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, - oSendEnv, oControlPath, oControlMaster, oControlPersist, - oHashKnownHosts, -@@ -166,10 +167,18 @@ static struct { - { "afstokenpassing", oUnsupported }, - #if defined(GSSAPI) - { "gssapiauthentication", oGssAuthentication }, -+ { "gssapikeyexchange", oGssKeyEx }, - { "gssapidelegatecredentials", oGssDelegateCreds }, -+ { "gssapitrustdns", oGssTrustDns }, -+ { "gssapiclientidentity", oGssClientIdentity }, -+ { "gssapirenewalforcesrekey", oGssRenewalRekey }, - #else - { "gssapiauthentication", oUnsupported }, -+ { "gssapikeyexchange", oUnsupported }, - { "gssapidelegatecredentials", oUnsupported }, -+ { "gssapitrustdns", oUnsupported }, -+ { "gssapiclientidentity", oUnsupported }, -+ { "gssapirenewalforcesrekey", oUnsupported }, - #endif - { "fallbacktorsh", oDeprecated }, - { "usersh", oDeprecated }, -@@ -474,10 +483,26 @@ 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 oGssRenewalRekey: -+ intptr = &options->gss_renewal_rekey; -+ goto parse_flag; -+ - case oBatchMode: - intptr = &options->batch_mode; - goto parse_flag; -@@ -1058,7 +1083,11 @@ 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->password_authentication = -1; - options->kbd_interactive_authentication = -1; - options->kbd_interactive_devices = NULL; -@@ -1156,8 +1185,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-5.6p1/readconf.h.gsskex openssh-5.6p1/readconf.h ---- openssh-5.6p1/readconf.h.gsskex 2010-08-03 08:04:46.000000000 +0200 -+++ openssh-5.6p1/readconf.h 2011-01-24 23:51:09.000000000 +0100 -@@ -46,7 +46,11 @@ 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 */ - int password_authentication; /* Try password - * authentication. */ - int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ -diff -up openssh-5.6p1/servconf.c.gsskex openssh-5.6p1/servconf.c ---- openssh-5.6p1/servconf.c.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/servconf.c 2011-01-24 23:51:09.000000000 +0100 -@@ -93,7 +93,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; -@@ -218,8 +221,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) -@@ -313,7 +322,9 @@ typedef enum { - sBanner, sShowPatchLevel, sUseDNS, sHostbasedAuthentication, - sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, - sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, -- sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, -+ sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, -+ sGssKeyEx, sGssStoreRekey, -+ sAcceptEnv, sPermitTunnel, - sMatch, sPermitOpen, sForceCommand, sChrootDirectory, - sUsePrivilegeSeparation, sAllowAgentForwarding, - sZeroKnowledgePasswordAuthentication, sHostCertificate, -@@ -377,9 +388,15 @@ static struct { - #ifdef GSSAPI - { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, - { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, -+ { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, -+ { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, -+ { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, - #else - { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, - { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, -+ { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, -+ { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, -+ { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, - #endif - { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, - { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, -@@ -941,10 +958,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; -diff -up openssh-5.6p1/servconf.h.gsskex openssh-5.6p1/servconf.h ---- openssh-5.6p1/servconf.h.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/servconf.h 2011-01-24 23:51:09.000000000 +0100 -@@ -94,7 +94,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-5.6p1/ssh_config.5.gsskex openssh-5.6p1/ssh_config.5 ---- openssh-5.6p1/ssh_config.5.gsskex 2010-08-05 05:03:13.000000000 +0200 -+++ openssh-5.6p1/ssh_config.5 2011-01-24 23:51:09.000000000 +0100 -@@ -509,11 +509,38 @@ 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 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-5.6p1/ssh_config.gsskex openssh-5.6p1/ssh_config ---- openssh-5.6p1/ssh_config.gsskex 2011-01-24 23:51:07.000000000 +0100 -+++ openssh-5.6p1/ssh_config 2011-01-24 23:51:09.000000000 +0100 -@@ -26,6 +26,8 @@ - # HostbasedAuthentication no - # GSSAPIAuthentication no - # GSSAPIDelegateCredentials no -+# GSSAPIKeyExchange no -+# GSSAPITrustDNS no - # BatchMode no - # CheckHostIP yes - # AddressFamily any -diff -up openssh-5.6p1/sshconnect2.c.gsskex openssh-5.6p1/sshconnect2.c ---- openssh-5.6p1/sshconnect2.c.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/sshconnect2.c 2011-01-24 23:51:09.000000000 +0100 -@@ -108,9 +108,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; -@@ -146,6 +171,17 @@ ssh_kex2(char *host, struct sockaddr *ho - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = - options.hostkeyalgorithms; - -+#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); - -@@ -155,10 +191,26 @@ ssh_kex2(char *host, struct sockaddr *ho - kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; - kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; - kex->kex[KEX_DH_GEX_SHA256] = kexgex_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; -+ kex->gss_host = gss_host; -+ } -+#endif -+ - xxx_kex = kex; - - dispatch_run(DISPATCH_BLOCK, &kex->done, kex); -@@ -253,6 +305,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 *); -@@ -268,6 +321,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, -@@ -574,25 +632,37 @@ userauth_gssapi(Authctxt *authctxt) - static u_int mech = 0; - OM_uint32 min; - int ok = 0; -- char* remotehost = NULL; -+ const char* remotehost = NULL; - const char* canonicalhost = get_canonical_hostname(1); -+ const char *gss_host; -+ - if ( strcmp( canonicalhost, "UNKNOWN" ) == 0 ) - remotehost = authctxt->host; - else - remotehost = canonicalhost; - -+ if (options.gss_trust_dns) -+// gss_host = get_canonical_hostname(1); -+ gss_host = remotehost; -+ 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], remotehost)) { -+ &gss_supported->elements[mech], gss_host, -+ options.gss_client_identity)) { - ok = 1; /* Mechanism works */ - } else { - mech++; -@@ -689,8 +759,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"); -@@ -800,6 +870,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-5.6p1/sshd.c.gsskex openssh-5.6p1/sshd.c ---- openssh-5.6p1/sshd.c.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/sshd.c 2011-01-24 23:51:09.000000000 +0100 -@@ -130,6 +130,10 @@ int allow_severity; - int deny_severity; - #endif /* LIBWRAP */ - -+#ifdef USE_SECURITY_SESSION_API -+#include -+#endif -+ - #ifndef O_NOCTTY - #define O_NOCTTY 0 - #endif -@@ -1603,10 +1607,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); -@@ -1939,6 +1946,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 -@@ -2335,12 +2396,61 @@ 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; - kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; - kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; - kex->kex[KEX_DH_GEX_SHA256] = kexgex_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-5.6p1/sshd_config.5.gsskex openssh-5.6p1/sshd_config.5 ---- openssh-5.6p1/sshd_config.5.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/sshd_config.5 2011-01-24 23:51:09.000000000 +0100 -@@ -424,12 +424,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-5.6p1/sshd_config.gsskex openssh-5.6p1/sshd_config ---- openssh-5.6p1/sshd_config.gsskex 2011-01-24 23:51:08.000000000 +0100 -+++ openssh-5.6p1/sshd_config 2011-01-24 23:51:09.000000000 +0100 -@@ -78,6 +78,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-5.6p1/ssh-gss.h.gsskex openssh-5.6p1/ssh-gss.h ---- openssh-5.6p1/ssh-gss.h.gsskex 2007-06-12 15:40:39.000000000 +0200 -+++ openssh-5.6p1/ssh-gss.h 2011-01-24 23:51:09.000000000 +0100 -@@ -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-5.6p1-kuserok.patch b/openssh-5.6p1-kuserok.patch deleted file mode 100644 index 7376a85..0000000 --- a/openssh-5.6p1-kuserok.patch +++ /dev/null @@ -1,167 +0,0 @@ -diff -up openssh-5.6p1/auth-krb5.c.kuserok openssh-5.6p1/auth-krb5.c ---- openssh-5.6p1/auth-krb5.c.kuserok 2010-11-15 10:08:05.000000000 +0100 -+++ openssh-5.6p1/auth-krb5.c 2010-11-15 10:11:02.000000000 +0100 -@@ -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.6p1/gss-serv-krb5.c.kuserok openssh-5.6p1/gss-serv-krb5.c ---- openssh-5.6p1/gss-serv-krb5.c.kuserok 2010-11-15 10:08:05.000000000 +0100 -+++ openssh-5.6p1/gss-serv-krb5.c 2010-11-15 10:12:35.000000000 +0100 -@@ -57,6 +57,7 @@ extern ServerOptions options; - #endif - - 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 */ - -@@ -97,7 +98,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client - krb5_get_err_text(krb_context, retval)); - return 0; - } -- if (krb5_kuserok(krb_context, princ, name)) { -+ if (ssh_krb5_kuserok(krb_context, princ, name)) { - retval = 1; - logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", - name, (char *)client->displayname.value); -diff -up openssh-5.6p1/servconf.c.kuserok openssh-5.6p1/servconf.c ---- openssh-5.6p1/servconf.c.kuserok 2010-11-15 10:08:05.000000000 +0100 -+++ openssh-5.6p1/servconf.c 2010-11-15 10:08:05.000000000 +0100 -@@ -138,6 +138,7 @@ initialize_server_options(ServerOptions - options->revoked_keys_file = NULL; - options->trusted_user_ca_keys = NULL; - options->authorized_principals_file = NULL; -+ options->use_kuserok = -1; - } - - void -@@ -286,6 +287,8 @@ fill_default_server_options(ServerOption - if (use_privsep == -1) - use_privsep = 1; - -+ if (options->use_kuserok == -1) -+ options->use_kuserok = 1; - #ifndef HAVE_MMAP - if (use_privsep && options->compression == 1) { - error("This platform does not support both privilege " -@@ -307,7 +310,7 @@ typedef enum { - sPermitRootLogin, sLogFacility, sLogLevel, - sRhostsRSAAuthentication, sRSAAuthentication, - sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, -- sKerberosGetAFSToken, -+ sKerberosGetAFSToken, sKerberosUseKuserok, - sKerberosTgtPassing, sChallengeResponseAuthentication, - sPasswordAuthentication, sKbdInteractiveAuthentication, - sListenAddress, sAddressFamily, -@@ -377,11 +380,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 }, -@@ -1341,6 +1346,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') -@@ -1525,6 +1534,7 @@ copy_set_server_options(ServerOptions *d - M_CP_INTOPT(x11_use_localhost); - M_CP_INTOPT(max_sessions); - M_CP_INTOPT(max_authtries); -+ M_CP_INTOPT(use_kuserok); - - M_CP_STROPT(banner); - if (preauth) -@@ -1745,6 +1755,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.6p1/servconf.h.kuserok openssh-5.6p1/servconf.h ---- openssh-5.6p1/servconf.h.kuserok 2010-11-15 10:08:05.000000000 +0100 -+++ openssh-5.6p1/servconf.h 2010-11-15 10:08:05.000000000 +0100 -@@ -157,6 +157,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.6p1/sshd_config.5.kuserok openssh-5.6p1/sshd_config.5 ---- openssh-5.6p1/sshd_config.5.kuserok 2010-11-15 10:08:05.000000000 +0100 -+++ openssh-5.6p1/sshd_config.5 2010-11-15 10:08:05.000000000 +0100 -@@ -564,6 +564,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 KeyRegenerationInterval - In protocol version 1, the ephemeral server key is automatically regenerated - after this many seconds (if it has been used). -@@ -694,6 +698,7 @@ Available keywords are - .Cm HostbasedUsesNameFromPacketOnly , - .Cm KbdInteractiveAuthentication , - .Cm KerberosAuthentication , -+.Cm KerberosUseKuserok , - .Cm MaxAuthTries , - .Cm MaxSessions , - .Cm PubkeyAuthentication , -diff -up openssh-5.6p1/sshd_config.kuserok openssh-5.6p1/sshd_config ---- openssh-5.6p1/sshd_config.kuserok 2010-11-15 10:08:05.000000000 +0100 -+++ openssh-5.6p1/sshd_config 2010-11-15 10:08:05.000000000 +0100 -@@ -72,6 +72,7 @@ ChallengeResponseAuthentication no - #KerberosOrLocalPasswd yes - #KerberosTicketCleanup yes - #KerberosGetAFSToken no -+#KerberosUseKuserok yes - - # GSSAPI options - #GSSAPIAuthentication no diff --git a/openssh-5.6p1-mls.patch b/openssh-5.6p1-mls.patch deleted file mode 100644 index ee8a8ef..0000000 --- a/openssh-5.6p1-mls.patch +++ /dev/null @@ -1,430 +0,0 @@ -diff -up openssh-5.6p1/configure.ac.mls openssh-5.6p1/configure.ac ---- openssh-5.6p1/configure.ac.mls 2010-08-23 12:11:36.000000000 +0200 -+++ openssh-5.6p1/configure.ac 2010-08-23 12:11:36.000000000 +0200 -@@ -3390,6 +3390,7 @@ AC_ARG_WITH(selinux, - SSHDLIBS="$SSHDLIBS $LIBSELINUX" - LIBS="$LIBS $LIBSELINUX" - AC_CHECK_FUNCS(getseuserbyname get_default_context_with_level) -+ AC_CHECK_FUNCS(setkeycreatecon) - LIBS="$save_LIBS" - fi ] - ) -diff -up openssh-5.6p1/misc.c.mls openssh-5.6p1/misc.c ---- openssh-5.6p1/misc.c.mls 2010-08-03 08:05:05.000000000 +0200 -+++ openssh-5.6p1/misc.c 2010-08-23 12:14:16.000000000 +0200 -@@ -424,6 +424,7 @@ char * - colon(char *cp) - { - int flag = 0; -+ int start = 1; - - if (*cp == ':') /* Leading colon is part of file name. */ - return NULL; -@@ -439,6 +440,13 @@ colon(char *cp) - return (cp); - if (*cp == '/') - return NULL; -+ if (start) { -+ /* Slash on beginning or after dots only denotes file name. */ -+ if (*cp == '/') -+ return (0); -+ if (*cp != '.') -+ start = 0; -+ } - } - return NULL; - } -diff -up openssh-5.6p1/openbsd-compat/port-linux.c.mls openssh-5.6p1/openbsd-compat/port-linux.c ---- openssh-5.6p1/openbsd-compat/port-linux.c.mls 2010-08-23 12:11:36.000000000 +0200 -+++ openssh-5.6p1/openbsd-compat/port-linux.c 2010-08-23 12:11:37.000000000 +0200 -@@ -35,13 +35,24 @@ - #include "key.h" - #include "hostfile.h" - #include "auth.h" -+#include "xmalloc.h" - - #ifdef WITH_SELINUX - #include - #include -+#include - #include -+#include -+#include -+ -+#ifdef HAVE_LINUX_AUDIT -+#include -+#include -+#endif - - extern Authctxt *the_authctxt; -+extern int inetd_flag; -+extern int rexeced_flag; - - /* Wrapper around is_selinux_enabled() to log its return value once only */ - int -@@ -57,17 +68,173 @@ ssh_selinux_enabled(void) - return (enabled); - } - -+/* Send audit message */ -+static int -+send_audit_message(int success, security_context_t default_context, -+ security_context_t selected_context) -+{ -+ int rc=0; -+#ifdef HAVE_LINUX_AUDIT -+ char *msg = NULL; -+ int audit_fd = audit_open(); -+ security_context_t default_raw=NULL; -+ security_context_t selected_raw=NULL; -+ rc = -1; -+ if (audit_fd < 0) { -+ if (errno == EINVAL || errno == EPROTONOSUPPORT || -+ errno == EAFNOSUPPORT) -+ return 0; /* No audit support in kernel */ -+ error("Error connecting to audit system."); -+ return rc; -+ } -+ if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) { -+ error("Error translating default context."); -+ default_raw = NULL; -+ } -+ if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) { -+ error("Error translating selected context."); -+ selected_raw = NULL; -+ } -+ if (asprintf(&msg, "sshd: default-context=%s selected-context=%s", -+ default_raw ? default_raw : (default_context ? default_context: "?"), -+ selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) { -+ error("Error allocating memory."); -+ goto out; -+ } -+ if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE, -+ msg, NULL, NULL, NULL, success) <= 0) { -+ error("Error sending audit message."); -+ goto out; -+ } -+ rc = 0; -+ out: -+ free(msg); -+ freecon(default_raw); -+ freecon(selected_raw); -+ close(audit_fd); -+#endif -+ return rc; -+} -+ -+static int -+mls_range_allowed(security_context_t src, security_context_t dst) -+{ -+ struct av_decision avd; -+ int retval; -+ unsigned int bit = CONTEXT__CONTAINS; -+ -+ debug("%s: src:%s dst:%s", __func__, src, dst); -+ retval = security_compute_av(src, dst, SECCLASS_CONTEXT, bit, &avd); -+ if (retval || ((bit & avd.allowed) != bit)) -+ return 0; -+ -+ return 1; -+} -+ -+static int -+get_user_context(const char *sename, const char *role, const char *lvl, -+ security_context_t *sc) { -+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL -+ if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) { -+ /* User may have requested a level completely outside of his -+ allowed range. We get a context just for auditing as the -+ range check below will certainly fail for default context. */ -+#endif -+ if (get_default_context(sename, NULL, sc) != 0) { -+ *sc = NULL; -+ return -1; -+ } -+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL -+ } -+#endif -+ if (role != NULL && role[0]) { -+ context_t con; -+ char *type=NULL; -+ if (get_default_type(role, &type) != 0) { -+ error("get_default_type: failed to get default type for '%s'", -+ role); -+ goto out; -+ } -+ con = context_new(*sc); -+ if (!con) { -+ goto out; -+ } -+ context_role_set(con, role); -+ context_type_set(con, type); -+ freecon(*sc); -+ *sc = strdup(context_str(con)); -+ context_free(con); -+ if (!*sc) -+ return -1; -+ } -+#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL -+ if (lvl != NULL && lvl[0]) { -+ /* verify that the requested range is obtained */ -+ context_t con; -+ security_context_t obtained_raw; -+ security_context_t requested_raw; -+ con = context_new(*sc); -+ if (!con) { -+ goto out; -+ } -+ context_range_set(con, lvl); -+ if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) { -+ context_free(con); -+ goto out; -+ } -+ if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) { -+ freecon(obtained_raw); -+ context_free(con); -+ goto out; -+ } -+ -+ debug("get_user_context: obtained context '%s' requested context '%s'", -+ obtained_raw, requested_raw); -+ if (strcmp(obtained_raw, requested_raw)) { -+ /* set the context to the real requested one but fail */ -+ freecon(requested_raw); -+ freecon(obtained_raw); -+ freecon(*sc); -+ *sc = strdup(context_str(con)); -+ context_free(con); -+ return -1; -+ } -+ freecon(requested_raw); -+ freecon(obtained_raw); -+ context_free(con); -+ } -+#endif -+ return 0; -+ out: -+ freecon(*sc); -+ *sc = NULL; -+ return -1; -+} -+ - /* Return the default security context for the given username */ --static security_context_t --ssh_selinux_getctxbyname(char *pwname) -+static int -+ssh_selinux_getctxbyname(char *pwname, -+ security_context_t *default_sc, security_context_t *user_sc) - { -- security_context_t sc = NULL; - char *sename, *lvl; -+ const char *reqlvl = NULL; - char *role = NULL; -- int r = 0; -+ int r = -1; -+ context_t con = NULL; -+ -+ *default_sc = NULL; -+ *user_sc = NULL; -+ if (the_authctxt) { -+ if (the_authctxt->role != NULL) { -+ char *slash; -+ role = xstrdup(the_authctxt->role); -+ if ((slash = strchr(role, '/')) != NULL) { -+ *slash = '\0'; -+ reqlvl = slash + 1; -+ } -+ } -+ } - -- if (the_authctxt) -- role=the_authctxt->role; - #ifdef HAVE_GETSEUSERBYNAME - if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) { - sename = NULL; -@@ -75,38 +242,63 @@ ssh_selinux_getctxbyname(char *pwname) - } - #else - sename = pwname; -- lvl = NULL; -+ lvl = ""; - #endif - - if (r == 0) { - #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL -- if (role != NULL && role[0]) -- r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc); -- else -- r = get_default_context_with_level(sename, lvl, NULL, &sc); -+ r = get_default_context_with_level(sename, lvl, NULL, default_sc); - #else -- if (role != NULL && role[0]) -- r = get_default_context_with_role(sename, role, NULL, &sc); -- else -- r = get_default_context(sename, NULL, &sc); -+ r = get_default_context(sename, NULL, default_sc); - #endif - } - -- if (r != 0) { -- switch (security_getenforce()) { -- case -1: -- fatal("%s: ssh_selinux_getctxbyname: " -- "security_getenforce() failed", __func__); -- case 0: -- error("%s: Failed to get default SELinux security " -- "context for %s", __func__, pwname); -- break; -- default: -- fatal("%s: Failed to get default SELinux security " -- "context for %s (in enforcing mode)", -- __func__, pwname); -+ if (r == 0) { -+ /* If launched from xinetd, we must use current level */ -+ if (inetd_flag && !rexeced_flag) { -+ security_context_t sshdsc=NULL; -+ -+ if (getcon_raw(&sshdsc) < 0) -+ fatal("failed to allocate security context"); -+ -+ if ((con=context_new(sshdsc)) == NULL) -+ fatal("failed to allocate selinux context"); -+ reqlvl = context_range_get(con); -+ freecon(sshdsc); -+ if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0) -+ /* we actually don't change level */ -+ reqlvl = ""; -+ -+ debug("%s: current connection level '%s'", __func__, reqlvl); -+ } -+ -+ if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) { -+ r = get_user_context(sename, role, reqlvl, user_sc); -+ -+ if (r == 0 && reqlvl != NULL && reqlvl[0]) { -+ security_context_t default_level_sc = *default_sc; -+ if (role != NULL && role[0]) { -+ if (get_user_context(sename, role, lvl, &default_level_sc) < 0) -+ default_level_sc = *default_sc; -+ } -+ /* verify that the requested range is contained in the user range */ -+ if (mls_range_allowed(default_level_sc, *user_sc)) { -+ logit("permit MLS level %s (user range %s)", reqlvl, lvl); -+ } else { -+ r = -1; -+ error("deny MLS level %s (user range %s)", reqlvl, lvl); -+ } -+ if (default_level_sc != *default_sc) -+ freecon(default_level_sc); -+ } -+ } else { -+ *user_sc = *default_sc; - } - } -+ if (r != 0) { -+ error("%s: Failed to get default SELinux security " -+ "context for %s", __func__, pwname); -+ } - - #ifdef HAVE_GETSEUSERBYNAME - if (sename != NULL) -@@ -114,14 +306,20 @@ ssh_selinux_getctxbyname(char *pwname) - if (lvl != NULL) - xfree(lvl); - #endif -+ if (role != NULL) -+ xfree(role); -+ if (con) -+ context_free(con); - -- return (sc); -+ return (r); - } - - /* Set the execution context to the default for the specified user */ - void - ssh_selinux_setup_exec_context(char *pwname) - { -+ int r = 0; -+ security_context_t default_ctx = NULL; - security_context_t user_ctx = NULL; - - if (!ssh_selinux_enabled()) -@@ -129,22 +327,45 @@ ssh_selinux_setup_exec_context(char *pwn - - debug3("%s: setting execution context", __func__); - -- user_ctx = ssh_selinux_getctxbyname(pwname); -- if (setexeccon(user_ctx) != 0) { -+ r = ssh_selinux_getctxbyname(pwname, &default_ctx, &user_ctx); -+ if (r >= 0) { -+ r = setexeccon(user_ctx); -+ if (r < 0) { -+ error("%s: Failed to set SELinux execution context %s for %s", -+ __func__, user_ctx, pwname); -+ } -+#ifdef HAVE_SETKEYCREATECON -+ else if (setkeycreatecon(user_ctx) < 0) { -+ error("%s: Failed to set SELinux keyring creation context %s for %s", -+ __func__, user_ctx, pwname); -+ } -+#endif -+ } -+ if (user_ctx == NULL) { -+ user_ctx = default_ctx; -+ } -+ if (r < 0 || user_ctx != default_ctx) { -+ /* audit just the case when user changed a role or there was -+ a failure */ -+ send_audit_message(r >= 0, default_ctx, user_ctx); -+ } -+ if (r < 0) { - switch (security_getenforce()) { - case -1: - fatal("%s: security_getenforce() failed", __func__); - case 0: -- error("%s: Failed to set SELinux execution " -- "context for %s", __func__, pwname); -+ error("%s: SELinux failure. Continuing in permissive mode.", -+ __func__); - break; - default: -- fatal("%s: Failed to set SELinux execution context " -- "for %s (in enforcing mode)", __func__, pwname); -+ fatal("%s: SELinux failure. Aborting connection.", -+ __func__); - } - } -- if (user_ctx != NULL) -+ if (user_ctx != NULL && user_ctx != default_ctx) - freecon(user_ctx); -+ if (default_ctx != NULL) -+ freecon(default_ctx); - - debug3("%s: done", __func__); - } -@@ -162,7 +383,10 @@ ssh_selinux_setup_pty(char *pwname, cons - - debug3("%s: setting TTY context on %s", __func__, tty); - -- user_ctx = ssh_selinux_getctxbyname(pwname); -+ if (getexeccon(&user_ctx) < 0) { -+ error("%s: getexeccon: %s", __func__, strerror(errno)); -+ goto out; -+ } - - /* XXX: should these calls fatal() upon failure in enforcing mode? */ - -diff -up openssh-5.6p1/sshd.c.mls openssh-5.6p1/sshd.c ---- openssh-5.6p1/sshd.c.mls 2010-08-23 12:11:36.000000000 +0200 -+++ openssh-5.6p1/sshd.c 2010-08-23 12:11:37.000000000 +0200 -@@ -1997,6 +1997,9 @@ main(int ac, char **av) - restore_uid(); - } - #endif -+#ifdef WITH_SELINUX -+ ssh_selinux_setup_exec_context(authctxt->pw->pw_name); -+#endif - #ifdef USE_PAM - if (options.use_pam) { - do_pam_setcred(1); diff --git a/openssh-5.8p1-audit2.patch b/openssh-5.8p1-audit2.patch new file mode 100644 index 0000000..362d7d3 --- /dev/null +++ b/openssh-5.8p1-audit2.patch @@ -0,0 +1,264 @@ +diff -up openssh-5.8p1/audit-bsm.c.audit2 openssh-5.8p1/audit-bsm.c +--- openssh-5.8p1/audit-bsm.c.audit2 2011-01-17 11:15:29.000000000 +0100 ++++ openssh-5.8p1/audit-bsm.c 2011-02-09 15:50:28.000000000 +0100 +@@ -316,6 +316,12 @@ audit_session_close(struct logininfo *li + /* not implemented */ + } + ++int ++audit_keyusage(int host_user, const char *type, unsigned len, char *fp, int rv) ++{ ++ /* not implemented */ ++} ++ + void + audit_event(ssh_audit_event_t event) + { +diff -up openssh-5.8p1/audit.c.audit2 openssh-5.8p1/audit.c +--- openssh-5.8p1/audit.c.audit2 2011-01-17 11:15:30.000000000 +0100 ++++ openssh-5.8p1/audit.c 2011-02-09 15:50:28.000000000 +0100 +@@ -111,6 +111,33 @@ audit_event_lookup(ssh_audit_event_t ev) + return(event_lookup[i].name); + } + ++int ++audit_key(int type, int *rv, const Key *key) ++{ ++ char *fp; ++ unsigned size = 0; ++ const char *crypto_name[] = { ++ "ssh-rsa1", ++ "ssh-rsa", ++ "ssh-dsa", ++ "unknown" }; ++ ++ fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); ++ switch(key->type) { ++ case KEY_RSA1: ++ case KEY_RSA: ++ size = RSA_size(key->rsa); ++ break; ++ case KEY_DSA: ++ size = DSA_size(key->dsa); ++ break; ++ } ++ ++ if (audit_keyusage(0, crypto_name[key->type], size, fp, *rv) == 0) ++ *rv = 0; ++ xfree(fp); ++} ++ + # ifndef CUSTOM_SSH_AUDIT_EVENTS + /* + * Null implementations of audit functions. +@@ -182,5 +209,17 @@ audit_run_command(const char *command) + debug("audit run command euid %d user %s command '%.200s'", geteuid(), + audit_username(), command); + } ++ ++/* ++ * This will be called when user is successfully autherized by the RSA1/RSA/DSA key. ++ * ++ * Type is the key type, len is the key length(byte) and fp is the fingerprint of the key. ++ */ ++int ++audit_keyusage(int host_user, const char *type, unsigned len, char *fp, int rv) ++{ ++ debug("audit %s key usage euid %d user %s key type %s key length %d fingerprint %s, result %d", ++ host_user ? "hostbased" : "pubkey", geteuid(), audit_username(), type, len, fp, rv); ++} + # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ + #endif /* SSH_AUDIT_EVENTS */ +diff -up openssh-5.8p1/audit.h.audit2 openssh-5.8p1/audit.h +--- openssh-5.8p1/audit.h.audit2 2011-01-17 11:15:30.000000000 +0100 ++++ openssh-5.8p1/audit.h 2011-02-09 15:50:28.000000000 +0100 +@@ -28,6 +28,7 @@ + # define _SSH_AUDIT_H + + #include "loginrec.h" ++#include "key.h" + + enum ssh_audit_event_type { + SSH_LOGIN_EXCEED_MAXTRIES, +@@ -53,5 +54,7 @@ void audit_session_open(struct logininfo + void audit_session_close(struct logininfo *); + void audit_run_command(const char *); + ssh_audit_event_t audit_classify_auth(const char *); ++int audit_keyusage(int, const char *, unsigned, char *, int); ++int audit_key(int, int *, const Key *); + + #endif /* _SSH_AUDIT_H */ +diff -up openssh-5.8p1/audit-linux.c.audit2 openssh-5.8p1/audit-linux.c +--- openssh-5.8p1/audit-linux.c.audit2 2011-01-17 11:15:30.000000000 +0100 ++++ openssh-5.8p1/audit-linux.c 2011-02-09 15:51:45.000000000 +0100 +@@ -37,6 +37,8 @@ + #include "audit.h" + #include "canohost.h" + ++#define AUDIT_LOG_SIZE 128 ++ + const char* audit_username(void); + + int +@@ -68,6 +70,37 @@ linux_audit_record_event(int uid, const + return (rc >= 0); + } + ++int ++audit_keyusage(int host_user, const char *type, unsigned len, char *fp, int rv) ++{ ++ char buf[AUDIT_LOG_SIZE]; ++ int audit_fd, rc, saved_errno; ++ ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno == EINVAL || errno == EPROTONOSUPPORT || ++ errno == EAFNOSUPPORT) ++ return 1; /* No audit support in kernel */ ++ else ++ return 0; /* Must prevent login */ ++ } ++ snprintf(buf, sizeof(buf), "%s_auth rport=%d", host_user ? "hostbased" : "pubkey", get_remote_port()); ++ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL, ++ buf, audit_username(), -1, NULL, get_remote_ipaddr(), NULL, rv); ++ if ((rc < 0) && ((rc != -1) || (getuid() == 0))) ++ goto out; ++ snprintf(buf, sizeof(buf), "key algo=%s size=%d fp=%s rport=%d", ++ type, 8 * len, fp, get_remote_port()); ++ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL, ++ buf, audit_username(), -1, NULL, get_remote_ipaddr(), NULL, rv); ++out: ++ saved_errno = errno; ++ audit_close(audit_fd); ++ errno = saved_errno; ++ /* do not report error if the error is EPERM and sshd is run as non root user */ ++ return (rc >= 0) || ((rc == -EPERM) && (getuid() != 0)); ++} ++ + /* Below is the sshd audit API code */ + + void +diff -up openssh-5.8p1/auth2-hostbased.c.audit2 openssh-5.8p1/auth2-hostbased.c +--- openssh-5.8p1/auth2-hostbased.c.audit2 2010-08-05 05:04:50.000000000 +0200 ++++ openssh-5.8p1/auth2-hostbased.c 2011-02-09 15:50:28.000000000 +0100 +@@ -136,6 +136,18 @@ done: + return authenticated; + } + ++int ++hostkey_key_verify(const Key *key, const u_char *sig, u_int slen, const u_char *data, u_int datalen) ++{ ++ int rv; ++ ++ rv = key_verify(key, sig, slen, data, datalen); ++#ifdef SSH_AUDIT_EVENTS ++ audit_key(0, &rv, key); ++#endif ++ return rv; ++} ++ + /* return 1 if given hostkey is allowed */ + int + hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, +diff -up openssh-5.8p1/auth2-pubkey.c.audit2 openssh-5.8p1/auth2-pubkey.c +--- openssh-5.8p1/auth2-pubkey.c.audit2 2010-12-01 01:50:14.000000000 +0100 ++++ openssh-5.8p1/auth2-pubkey.c 2011-02-09 15:50:28.000000000 +0100 +@@ -177,6 +177,18 @@ done: + return authenticated; + } + ++int ++pubkey_key_verify(const Key *key, const u_char *sig, u_int slen, const u_char *data, u_int datalen) ++{ ++ int rv; ++ ++ rv = key_verify(key, sig, slen, data, datalen); ++#ifdef SSH_AUDIT_EVENTS ++ audit_key(1, &rv, key); ++#endif ++ return rv; ++} ++ + static int + match_principals_option(const char *principal_list, struct KeyCert *cert) + { +diff -up openssh-5.8p1/auth.h.audit2 openssh-5.8p1/auth.h +--- openssh-5.8p1/auth.h.audit2 2010-05-10 03:58:03.000000000 +0200 ++++ openssh-5.8p1/auth.h 2011-02-09 15:50:28.000000000 +0100 +@@ -170,6 +170,7 @@ void abandon_challenge_response(Authctxt + char *authorized_keys_file(struct passwd *); + char *authorized_keys_file2(struct passwd *); + char *authorized_principals_file(struct passwd *); ++int pubkey_key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); + + FILE *auth_openkeyfile(const char *, struct passwd *, int); + FILE *auth_openprincipals(const char *, struct passwd *, int); +@@ -185,6 +186,7 @@ Key *get_hostkey_public_by_type(int); + Key *get_hostkey_private_by_type(int); + int get_hostkey_index(Key *); + int ssh1_session_key(BIGNUM *); ++int hostkey_key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); + + /* debug messages during authentication */ + void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); +diff -up openssh-5.8p1/auth-rsa.c.audit2 openssh-5.8p1/auth-rsa.c +--- openssh-5.8p1/auth-rsa.c.audit2 2010-12-04 23:01:47.000000000 +0100 ++++ openssh-5.8p1/auth-rsa.c 2011-02-09 15:53:00.000000000 +0100 +@@ -92,7 +92,10 @@ auth_rsa_verify_response(Key *key, BIGNU + { + u_char buf[32], mdbuf[16]; + MD5_CTX md; +- int len; ++ int len, rv; ++#ifdef SSH_AUDIT_EVENTS ++ char *fp; ++#endif + + /* don't allow short keys */ + if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { +@@ -113,12 +116,18 @@ auth_rsa_verify_response(Key *key, BIGNU + MD5_Final(mdbuf, &md); + + /* Verify that the response is the original challenge. */ +- if (timingsafe_bcmp(response, mdbuf, 16) != 0) { +- /* Wrong answer. */ +- return (0); ++ rv = timingsafe_bcmp(response, mdbuf, 16) == 0; ++ ++#ifdef SSH_AUDIT_EVENTS ++ fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); ++ if (audit_keyusage(1, "ssh-rsa1", RSA_size(key->rsa), fp, rv) == 0) { ++ debug("unsuccessful audit"); ++ rv = 0; + } +- /* Correct answer. */ +- return (1); ++ xfree(fp); ++#endif ++ ++ return rv; + } + + /* +diff -up openssh-5.8p1/monitor.c.audit2 openssh-5.8p1/monitor.c +--- openssh-5.8p1/monitor.c.audit2 2010-09-10 03:23:34.000000000 +0200 ++++ openssh-5.8p1/monitor.c 2011-02-09 15:50:28.000000000 +0100 +@@ -1235,7 +1235,17 @@ mm_answer_keyverify(int sock, Buffer *m) + if (!valid_data) + fatal("%s: bad signature data blob", __func__); + +- verified = key_verify(key, signature, signaturelen, data, datalen); ++ switch (key_blobtype) { ++ case MM_USERKEY: ++ verified = pubkey_key_verify(key, signature, signaturelen, data, datalen); ++ break; ++ case MM_HOSTKEY: ++ verified = hostkey_key_verify(key, signature, signaturelen, data, datalen); ++ break; ++ default: ++ verified = 0; ++ break; ++ } + debug3("%s: key %p signature %s", + __func__, key, (verified == 1) ? "verified" : "unverified"); + diff --git a/openssh-5.8p1-audit3.patch b/openssh-5.8p1-audit3.patch new file mode 100644 index 0000000..1c7f1a4 --- /dev/null +++ b/openssh-5.8p1-audit3.patch @@ -0,0 +1,502 @@ +diff -up openssh-5.8p1/audit-bsm.c.audit3 openssh-5.8p1/audit-bsm.c +--- openssh-5.8p1/audit-bsm.c.audit3 2011-02-09 21:51:19.000000000 +0100 ++++ openssh-5.8p1/audit-bsm.c 2011-02-09 21:51:19.000000000 +0100 +@@ -383,4 +383,16 @@ audit_event(ssh_audit_event_t event) + debug("%s: unhandled event %d", __func__, event); + } + } ++ ++void ++audit_unsupported_body(int what) ++{ ++ /* not implemented */ ++} ++ ++void ++audit_kex_body(int ctos, char *enc, char *mac, char *compress) ++{ ++ /* not implemented */ ++} + #endif /* BSM */ +diff -up openssh-5.8p1/audit.c.audit3 openssh-5.8p1/audit.c +--- openssh-5.8p1/audit.c.audit3 2011-02-09 21:51:19.000000000 +0100 ++++ openssh-5.8p1/audit.c 2011-02-09 21:51:19.000000000 +0100 +@@ -36,6 +36,8 @@ + #include "key.h" + #include "hostfile.h" + #include "auth.h" ++#include "ssh-gss.h" ++#include "monitor_wrap.h" + + /* + * Care must be taken when using this since it WILL NOT be initialized when +@@ -138,6 +140,18 @@ audit_key(int type, int *rv, const Key * + xfree(fp); + } + ++void ++audit_unsupported(int what) ++{ ++ PRIVSEP(audit_unsupported_body(what)); ++} ++ ++void ++audit_kex(int ctos, char *enc, char *mac, char *comp) ++{ ++ PRIVSEP(audit_kex_body(ctos, enc, mac, comp)); ++} ++ + # ifndef CUSTOM_SSH_AUDIT_EVENTS + /* + * Null implementations of audit functions. +@@ -221,5 +235,24 @@ audit_keyusage(int host_user, const char + debug("audit %s key usage euid %d user %s key type %s key length %d fingerprint %s, result %d", + host_user ? "hostbased" : "pubkey", geteuid(), audit_username(), type, len, fp, rv); + } ++ ++/* ++ * This will be called when the protocol negotiation fails. ++ */ ++void ++audit_unsupported_body(int what) ++{ ++ debug("audit unsupported protocol ieuid %d type %d", geteuid(), what); ++ ++ ++/* ++ * This will be called on succesfull protocol negotiation. ++ */ ++void ++audit_kex_body(int ctos, char *enc, char *mac, char *compress) ++{ ++ debug("audit procol negotiation euid %d direction %d cipher %s mac %s compresion %s", ++ geteuid(), ctos, enc, mac, compress); ++} + # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ + #endif /* SSH_AUDIT_EVENTS */ +diff -up openssh-5.8p1/audit.h.audit3 openssh-5.8p1/audit.h +--- openssh-5.8p1/audit.h.audit3 2011-02-09 21:51:19.000000000 +0100 ++++ openssh-5.8p1/audit.h 2011-02-09 21:51:19.000000000 +0100 +@@ -56,5 +56,9 @@ void audit_run_command(const char *); + ssh_audit_event_t audit_classify_auth(const char *); + int audit_keyusage(int, const char *, unsigned, char *, int); + int audit_key(int, int *, const Key *); ++void audit_unsupported(int); ++void audit_kex(int, char *, char *, char *); ++void audit_unsupported_body(int); ++void audit_kex_body(int, char *, char *, char *); + + #endif /* _SSH_AUDIT_H */ +diff -up openssh-5.8p1/audit-linux.c.audit3 openssh-5.8p1/audit-linux.c +--- openssh-5.8p1/audit-linux.c.audit3 2011-02-09 21:51:19.000000000 +0100 ++++ openssh-5.8p1/audit-linux.c 2011-02-09 21:51:19.000000000 +0100 +@@ -36,6 +36,8 @@ + #include "log.h" + #include "audit.h" + #include "canohost.h" ++#include "packet.h" ++#include "cipher.h" + + #define AUDIT_LOG_SIZE 128 + +@@ -156,4 +158,54 @@ audit_event(ssh_audit_event_t event) + } + } + ++void ++audit_unsupported_body(int what) ++{ ++#ifdef AUDIT_CRYPTO_SESSION ++ char buf[AUDIT_LOG_SIZE]; ++ const static char *name[] = { "cipher", "mac", "comp" }; ++ int audit_fd, audit_ok; ++ ++ snprintf(buf, sizeof(buf), "unsupported-%s direction=? cipher=? ksize=? rport=%d laddr=%s lport=%d", ++ name[what], get_remote_port(), get_local_ipaddr(packet_get_connection_in()), ++ get_local_port()); ++ audit_fd = audit_open(); ++ if (audit_fd < 0) ++ /* no problem, the next instruction will be fatal() */ ++ return; ++ audit_ok = audit_log_acct_message(audit_fd, AUDIT_CRYPTO_SESSION, NULL, ++ buf, NULL, -1, NULL, get_remote_ipaddr(), NULL, 0); ++ audit_close(audit_fd); ++#endif ++} ++ ++void ++audit_kex_body(int ctos, char *enc, char *mac, char *compress) ++{ ++#ifdef AUDIT_CRYPTO_SESSION ++ char buf[AUDIT_LOG_SIZE]; ++ int audit_fd, audit_ok; ++ const static char *direction[] = { "from-server", "from-client", "both" }; ++ Cipher *cipher = cipher_by_name(enc); ++ ++ snprintf(buf, sizeof(buf), "start direction=%s cipher=%s, ksize=%d rport=%d laddr=%s lport=%d", ++ direction[ctos], enc, cipher ? 8 * cipher->key_len : 0, ++ get_remote_port(), get_local_ipaddr(packet_get_connection_in()), get_local_port()); ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno == EINVAL || errno == EPROTONOSUPPORT || ++ errno == EAFNOSUPPORT) ++ return; /* No audit support in kernel */ ++ else ++ fatal("cannot open audit"); /* Must prevent login */ ++ } ++ audit_ok = audit_log_acct_message(audit_fd, AUDIT_CRYPTO_SESSION, NULL, ++ buf, NULL, -1, NULL, get_remote_ipaddr(), NULL, 1); ++ audit_close(audit_fd); ++ /* do not abort if the error is EPERM and sshd is run as non root user */ ++ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) ++ fatal("cannot write into audit"); /* Must prevent login */ ++#endif ++} ++ + #endif /* USE_LINUX_AUDIT */ +diff -up openssh-5.8p1/auditstub.c.audit3 openssh-5.8p1/auditstub.c +--- openssh-5.8p1/auditstub.c.audit3 2011-02-09 21:51:19.000000000 +0100 ++++ openssh-5.8p1/auditstub.c 2011-02-09 21:51:19.000000000 +0100 +@@ -0,0 +1,39 @@ ++/* $Id: auditstub.c,v 1.1 jfch Exp $ */ ++ ++/* ++ * Copyright 2010 Red Hat, Inc. All rights reserved. ++ * Use is subject to license terms. ++ * ++ * 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. ++ * ++ * Red Hat author: Jan F. Chadima ++ */ ++ ++void ++audit_unsupported(int n) ++{ ++} ++ ++void ++audit_kex(int ctos, char *enc, char *mac, char *comp) ++{ ++} ++ +diff -up openssh-5.8p1/cipher.c.audit3 openssh-5.8p1/cipher.c +--- openssh-5.8p1/cipher.c.audit3 2011-02-09 15:24:23.000000000 +0100 ++++ openssh-5.8p1/cipher.c 2011-02-09 21:51:19.000000000 +0100 +@@ -59,15 +59,7 @@ extern void ssh1_3des_iv(EVP_CIPHER_CTX + extern const EVP_CIPHER *evp_aes_128_ctr(void); + extern void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); + +-struct Cipher { +- char *name; +- int number; /* for ssh1 only */ +- u_int block_size; +- u_int key_len; +- u_int discard_len; +- u_int cbc_mode; +- const EVP_CIPHER *(*evptype)(void); +-} ciphers[] = { ++struct Cipher ciphers[] = { + { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, EVP_enc_null }, + { "des", SSH_CIPHER_DES, 8, 8, 0, 1, EVP_des_cbc }, + { "3des", SSH_CIPHER_3DES, 8, 16, 0, 1, evp_ssh1_3des }, +diff -up openssh-5.8p1/cipher.h.audit3 openssh-5.8p1/cipher.h +--- openssh-5.8p1/cipher.h.audit3 2009-01-28 06:38:41.000000000 +0100 ++++ openssh-5.8p1/cipher.h 2011-02-09 21:51:19.000000000 +0100 +@@ -61,7 +61,16 @@ + typedef struct Cipher Cipher; + typedef struct CipherContext CipherContext; + +-struct Cipher; ++struct Cipher { ++ char *name; ++ int number; /* for ssh1 only */ ++ u_int block_size; ++ u_int key_len; ++ u_int discard_len; ++ u_int cbc_mode; ++ const EVP_CIPHER *(*evptype)(void); ++}; ++ + struct CipherContext { + int plaintext; + EVP_CIPHER_CTX evp; +diff -up openssh-5.8p1/kex.c.audit3 openssh-5.8p1/kex.c +--- openssh-5.8p1/kex.c.audit3 2010-09-24 14:11:14.000000000 +0200 ++++ openssh-5.8p1/kex.c 2011-02-09 21:51:19.000000000 +0100 +@@ -49,6 +49,7 @@ + #include "dispatch.h" + #include "monitor.h" + #include "roaming.h" ++#include "audit.h" + + #if OPENSSL_VERSION_NUMBER >= 0x00907000L + # if defined(HAVE_EVP_SHA256) +@@ -286,9 +287,13 @@ static void + choose_enc(Enc *enc, char *client, char *server) + { + char *name = match_list(client, server, NULL); +- if (name == NULL) ++ if (name == NULL) { ++#ifdef SSH_AUDIT_EVENTS ++ audit_unsupported(0); ++#endif + fatal("no matching cipher found: client %s server %s", + client, server); ++ } + if ((enc->cipher = cipher_by_name(name)) == NULL) + fatal("matching cipher is not supported: %s", name); + enc->name = name; +@@ -303,9 +308,13 @@ static void + choose_mac(Mac *mac, char *client, char *server) + { + char *name = match_list(client, server, NULL); +- if (name == NULL) ++ if (name == NULL) { ++#ifdef SSH_AUDIT_EVENTS ++ audit_unsupported(1); ++#endif + fatal("no matching mac found: client %s server %s", + client, server); ++ } + if (mac_setup(mac, name) < 0) + fatal("unsupported mac %s", name); + /* truncate the key */ +@@ -320,8 +329,12 @@ static void + choose_comp(Comp *comp, char *client, char *server) + { + char *name = match_list(client, server, NULL); +- if (name == NULL) ++ if (name == NULL) { ++#ifdef SSH_AUDIT_EVENTS ++ audit_unsupported(2); ++#endif + fatal("no matching comp found: client %s server %s", client, server); ++ } + if (strcmp(name, "zlib@openssh.com") == 0) { + comp->type = COMP_DELAYED; + } else if (strcmp(name, "zlib") == 0) { +@@ -446,6 +459,9 @@ kex_choose_conf(Kex *kex) + newkeys->enc.name, + newkeys->mac.name, + newkeys->comp.name); ++#ifdef SSH_AUDIT_EVENTS ++ audit_kex(ctos, newkeys->enc.name, newkeys->mac.name, newkeys->comp.name); ++#endif + } + choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); + choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], +diff -up openssh-5.8p1/Makefile.in.audit3 openssh-5.8p1/Makefile.in +--- openssh-5.8p1/Makefile.in.audit3 2011-02-04 01:42:13.000000000 +0100 ++++ openssh-5.8p1/Makefile.in 2011-02-09 21:53:15.000000000 +0100 +@@ -76,7 +76,7 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o b + 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 \ + msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o jpake.o \ +- schnorr.o ssh-pkcs11.o ++ schnorr.o ssh-pkcs11.o auditstub.o + + SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ + sshconnect.o sshconnect1.o sshconnect2.o mux.o \ +diff -up openssh-5.8p1/monitor.c.audit3 openssh-5.8p1/monitor.c +--- openssh-5.8p1/monitor.c.audit3 2011-02-09 21:51:19.000000000 +0100 ++++ openssh-5.8p1/monitor.c 2011-02-09 21:51:19.000000000 +0100 +@@ -89,6 +89,7 @@ + #include "ssh2.h" + #include "jpake.h" + #include "roaming.h" ++#include "audit.h" + + #ifdef GSSAPI + static Gssctxt *gsscontext = NULL; +@@ -177,6 +178,8 @@ int mm_answer_gss_checkmic(int, Buffer * + #ifdef SSH_AUDIT_EVENTS + int mm_answer_audit_event(int, Buffer *); + int mm_answer_audit_command(int, Buffer *); ++int mm_answer_audit_unsupported_body(int, Buffer *); ++int mm_answer_audit_kex_body(int, Buffer *); + #endif + + static Authctxt *authctxt; +@@ -225,6 +228,8 @@ struct mon_table mon_dispatch_proto20[] + #endif + #ifdef SSH_AUDIT_EVENTS + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, ++ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, ++ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, + #endif + #ifdef BSD_AUTH + {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, +@@ -261,6 +266,8 @@ struct mon_table mon_dispatch_postauth20 + #ifdef SSH_AUDIT_EVENTS + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, + {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, ++ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, ++ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, + #endif + {0, 0, NULL} + }; +@@ -292,6 +299,8 @@ struct mon_table mon_dispatch_proto15[] + #endif + #ifdef SSH_AUDIT_EVENTS + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, ++ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, ++ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, + #endif + {0, 0, NULL} + }; +@@ -303,6 +312,8 @@ struct mon_table mon_dispatch_postauth15 + #ifdef SSH_AUDIT_EVENTS + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, + {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, ++ {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, ++ {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, + #endif + {0, 0, NULL} + }; +@@ -2206,3 +2217,40 @@ mm_answer_jpake_check_confirm(int sock, + } + + #endif /* JPAKE */ ++ ++#ifdef SSH_AUDIT_EVENTS ++int ++mm_answer_audit_unsupported_body(int sock, Buffer *m) ++{ ++ int what; ++ ++ what = buffer_get_int(m); ++ ++ audit_unsupported_body(what); ++ ++ buffer_clear(m); ++ ++ mm_request_send(sock, MONITOR_ANS_AUDIT_UNSUPPORTED, m); ++ return 0; ++} ++ ++int ++mm_answer_audit_kex_body(int sock, Buffer *m) ++{ ++ int ctos, len; ++ char *cipher, *mac, *compress; ++ ++ ctos = buffer_get_int(m); ++ cipher = buffer_get_string(m, &len); ++ mac = buffer_get_string(m, &len); ++ compress = buffer_get_string(m, &len); ++ ++ audit_kex_body(ctos, cipher, mac, compress); ++ ++ buffer_clear(m); ++ ++ mm_request_send(sock, MONITOR_ANS_AUDIT_KEX, m); ++ return 0; ++} ++ ++#endif /* SSH_AUDIT_EVENTS */ +diff -up openssh-5.8p1/monitor.h.audit3 openssh-5.8p1/monitor.h +--- openssh-5.8p1/monitor.h.audit3 2008-11-05 06:20:46.000000000 +0100 ++++ openssh-5.8p1/monitor.h 2011-02-09 21:51:19.000000000 +0100 +@@ -66,6 +66,8 @@ enum monitor_reqtype { + MONITOR_REQ_JPAKE_STEP2, MONITOR_ANS_JPAKE_STEP2, + MONITOR_REQ_JPAKE_KEY_CONFIRM, MONITOR_ANS_JPAKE_KEY_CONFIRM, + MONITOR_REQ_JPAKE_CHECK_CONFIRM, MONITOR_ANS_JPAKE_CHECK_CONFIRM, ++ MONITOR_REQ_AUDIT_UNSUPPORTED, MONITOR_ANS_AUDIT_UNSUPPORTED, ++ MONITOR_REQ_AUDIT_KEX, MONITOR_ANS_AUDIT_KEX, + }; + + struct mm_master; +diff -up openssh-5.8p1/monitor_wrap.c.audit3 openssh-5.8p1/monitor_wrap.c +--- openssh-5.8p1/monitor_wrap.c.audit3 2010-08-31 14:41:14.000000000 +0200 ++++ openssh-5.8p1/monitor_wrap.c 2011-02-09 21:51:19.000000000 +0100 +@@ -1412,3 +1412,38 @@ mm_jpake_check_confirm(const BIGNUM *k, + return success; + } + #endif /* JPAKE */ ++ ++#ifdef SSH_AUDIT_EVENTS ++void ++mm_audit_unsupported_body(int what) ++{ ++ Buffer m; ++ ++ buffer_init(&m); ++ buffer_put_int(&m, what); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_UNSUPPORTED, &m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_UNSUPPORTED, ++ &m); ++ ++ buffer_free(&m); ++} ++ ++void ++mm_audit_kex_body(int ctos, char *cipher, char *mac, char *compress) ++{ ++ Buffer m; ++ ++ buffer_init(&m); ++ buffer_put_int(&m, ctos); ++ buffer_put_cstring(&m, cipher); ++ buffer_put_cstring(&m, mac); ++ buffer_put_cstring(&m, compress); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_KEX, &m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_KEX, ++ &m); ++ ++ buffer_free(&m); ++} ++#endif /* SSH_AUDIT_EVENTS */ +diff -up openssh-5.8p1/monitor_wrap.h.audit3 openssh-5.8p1/monitor_wrap.h +--- openssh-5.8p1/monitor_wrap.h.audit3 2009-03-05 14:58:22.000000000 +0100 ++++ openssh-5.8p1/monitor_wrap.h 2011-02-09 21:51:19.000000000 +0100 +@@ -74,6 +74,8 @@ void mm_sshpam_free_ctx(void *); + #include "audit.h" + void mm_audit_event(ssh_audit_event_t); + void mm_audit_run_command(const char *); ++void mm_audit_unsupported_body(int); ++void mm_audit_kex_body(int, char *, char *, char *); + #endif + + struct Session; +diff -up openssh-5.8p1/sshd.c.audit3 openssh-5.8p1/sshd.c +--- openssh-5.8p1/sshd.c.audit3 2011-01-11 07:20:31.000000000 +0100 ++++ openssh-5.8p1/sshd.c 2011-02-09 21:51:19.000000000 +0100 +@@ -118,6 +118,7 @@ + #endif + #include "monitor_wrap.h" + #include "roaming.h" ++#include "audit.h" + #include "version.h" + + #ifdef LIBWRAP +@@ -2182,6 +2183,10 @@ do_ssh1_kex(void) + if (cookie[i] != packet_get_char()) + packet_disconnect("IP Spoofing check bytes do not match."); + ++#ifdef SSH_AUDIT_EVENTS ++ audit_kex(2, cipher_name(cipher_type), "crc", "none"); ++#endif ++ + debug("Encryption type: %.200s", cipher_name(cipher_type)); + + /* Get the encrypted integer. */ diff --git a/openssh-5.8p1-audit4.patch b/openssh-5.8p1-audit4.patch new file mode 100644 index 0000000..1e03de4 --- /dev/null +++ b/openssh-5.8p1-audit4.patch @@ -0,0 +1,445 @@ +diff -up openssh-5.8p1/audit-bsm.c.audit4 openssh-5.8p1/audit-bsm.c +--- openssh-5.8p1/audit-bsm.c.audit4 2011-02-09 22:24:22.000000000 +0100 ++++ openssh-5.8p1/audit-bsm.c 2011-02-09 22:24:22.000000000 +0100 +@@ -395,4 +395,10 @@ audit_kex_body(int ctos, char *enc, char + { + /* not implemented */ + } ++ ++void ++audit_session_key_free_body(int ctos) ++{ ++ /* not implemented */ ++} + #endif /* BSM */ +diff -up openssh-5.8p1/audit.c.audit4 openssh-5.8p1/audit.c +--- openssh-5.8p1/audit.c.audit4 2011-02-09 22:24:22.000000000 +0100 ++++ openssh-5.8p1/audit.c 2011-02-09 22:24:22.000000000 +0100 +@@ -152,6 +152,12 @@ audit_kex(int ctos, char *enc, char *mac + PRIVSEP(audit_kex_body(ctos, enc, mac, comp)); + } + ++void ++audit_session_key_free(int ctos) ++{ ++ PRIVSEP(audit_session_key_free_body(ctos)); ++} ++ + # ifndef CUSTOM_SSH_AUDIT_EVENTS + /* + * Null implementations of audit functions. +@@ -254,5 +260,13 @@ audit_kex_body(int ctos, char *enc, char + debug("audit procol negotiation euid %d direction %d cipher %s mac %s compresion %s", + geteuid(), ctos, enc, mac, compress); + } ++ ++/* ++ * This will be called on succesfull session key discard ++ */ ++audit_session_key_free_body(int ctos) ++{ ++ debug("audit session key discard euid %d direction %d", geteuid(), ctos); ++} + # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ + #endif /* SSH_AUDIT_EVENTS */ +diff -up openssh-5.8p1/audit.h.audit4 openssh-5.8p1/audit.h +--- openssh-5.8p1/audit.h.audit4 2011-02-09 22:24:22.000000000 +0100 ++++ openssh-5.8p1/audit.h 2011-02-09 22:24:22.000000000 +0100 +@@ -60,5 +60,7 @@ void audit_unsupported(int); + void audit_kex(int, char *, char *, char *); + void audit_unsupported_body(int); + void audit_kex_body(int, char *, char *, char *); ++void audit_session_key_free(int ctos); ++void audit_session_key_free_body(int ctos); + + #endif /* _SSH_AUDIT_H */ +diff -up openssh-5.8p1/audit-linux.c.audit4 openssh-5.8p1/audit-linux.c +--- openssh-5.8p1/audit-linux.c.audit4 2011-02-09 22:24:22.000000000 +0100 ++++ openssh-5.8p1/audit-linux.c 2011-02-09 22:24:22.000000000 +0100 +@@ -179,13 +179,14 @@ audit_unsupported_body(int what) + #endif + } + ++const static char *direction[] = { "from-server", "from-client", "both" }; ++ + void + audit_kex_body(int ctos, char *enc, char *mac, char *compress) + { + #ifdef AUDIT_CRYPTO_SESSION + char buf[AUDIT_LOG_SIZE]; + int audit_fd, audit_ok; +- const static char *direction[] = { "from-server", "from-client", "both" }; + Cipher *cipher = cipher_by_name(enc); + + snprintf(buf, sizeof(buf), "start direction=%s cipher=%s, ksize=%d rport=%d laddr=%s lport=%d", +@@ -208,4 +209,26 @@ audit_kex_body(int ctos, char *enc, char + #endif + } + ++void ++audit_session_key_free_body(int ctos) ++{ ++ char buf[AUDIT_LOG_SIZE]; ++ int audit_fd, audit_ok; ++ ++ snprintf(buf, sizeof(buf), "destroy kind=session direction=%s", direction[ctos]); ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno != EINVAL && errno != EPROTONOSUPPORT && ++ errno != EAFNOSUPPORT) ++ error("cannot open audit"); ++ return; ++ } ++ audit_ok = audit_log_acct_message(audit_fd, AUDIT_CRYPTO_KEY_USER, NULL, ++ buf, NULL, -1, NULL, get_remote_ipaddr(), NULL, 1); ++ audit_close(audit_fd); ++ /* do not abort if the error is EPERM and sshd is run as non root user */ ++ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) ++ error("cannot write into audit"); ++} ++ + #endif /* USE_LINUX_AUDIT */ +diff -up openssh-5.8p1/auditstub.c.audit4 openssh-5.8p1/auditstub.c +--- openssh-5.8p1/auditstub.c.audit4 2011-02-09 22:24:22.000000000 +0100 ++++ openssh-5.8p1/auditstub.c 2011-02-09 22:24:22.000000000 +0100 +@@ -37,3 +37,7 @@ audit_kex(int ctos, char *enc, char *mac + { + } + ++void ++audit_session_key_free(int ctos) ++{ ++} +diff -up openssh-5.8p1/kex.c.audit4 openssh-5.8p1/kex.c +--- openssh-5.8p1/kex.c.audit4 2011-02-09 22:24:22.000000000 +0100 ++++ openssh-5.8p1/kex.c 2011-02-09 22:24:22.000000000 +0100 +@@ -624,3 +624,34 @@ dump_digest(char *msg, u_char *digest, i + fprintf(stderr, "\n"); + } + #endif ++ ++static void ++enc_destroy(Enc *enc) ++{ ++ if (enc == NULL) ++ return; ++ ++ if (enc->key) { ++ memset(enc->key, 0, enc->key_len); ++ xfree(enc->key); ++ } ++ ++ if (enc->iv) { ++ memset(enc->iv, 0, enc->block_size); ++ xfree(enc->iv); ++ } ++ ++ memset(enc, 0, sizeof(*enc)); ++} ++ ++void ++newkeys_destroy(Newkeys *newkeys) ++{ ++ if (newkeys == NULL) ++ return; ++ ++ enc_destroy(&newkeys->enc); ++ mac_destroy(&newkeys->mac); ++ memset(&newkeys->comp, 0, sizeof(newkeys->comp)); ++} ++ +diff -up openssh-5.8p1/kex.h.audit4 openssh-5.8p1/kex.h +--- openssh-5.8p1/kex.h.audit4 2010-09-24 14:11:14.000000000 +0200 ++++ openssh-5.8p1/kex.h 2011-02-09 22:24:22.000000000 +0100 +@@ -156,6 +156,8 @@ void kexgex_server(Kex *); + void kexecdh_client(Kex *); + void kexecdh_server(Kex *); + ++void newkeys_destroy(Newkeys *newkeys); ++ + void + kex_dh_hash(char *, char *, char *, int, char *, int, u_char *, int, + BIGNUM *, BIGNUM *, BIGNUM *, u_char **, u_int *); +diff -up openssh-5.8p1/mac.c.audit4 openssh-5.8p1/mac.c +--- openssh-5.8p1/mac.c.audit4 2008-06-13 02:58:50.000000000 +0200 ++++ openssh-5.8p1/mac.c 2011-02-09 22:24:22.000000000 +0100 +@@ -162,6 +162,20 @@ mac_clear(Mac *mac) + mac->umac_ctx = NULL; + } + ++void ++mac_destroy(Mac *mac) ++{ ++ if (mac == NULL) ++ return; ++ ++ if (mac->key) { ++ memset(mac->key, 0, mac->key_len); ++ xfree(mac->key); ++ } ++ ++ memset(mac, 0, sizeof(*mac)); ++} ++ + /* XXX copied from ciphers_valid */ + #define MAC_SEP "," + int +diff -up openssh-5.8p1/mac.h.audit4 openssh-5.8p1/mac.h +--- openssh-5.8p1/mac.h.audit4 2007-06-11 06:01:42.000000000 +0200 ++++ openssh-5.8p1/mac.h 2011-02-09 22:24:22.000000000 +0100 +@@ -28,3 +28,4 @@ int mac_setup(Mac *, char *); + int mac_init(Mac *); + u_char *mac_compute(Mac *, u_int32_t, u_char *, int); + void mac_clear(Mac *); ++void mac_destroy(Mac *); +diff -up openssh-5.8p1/monitor.c.audit4 openssh-5.8p1/monitor.c +--- openssh-5.8p1/monitor.c.audit4 2011-02-09 22:24:22.000000000 +0100 ++++ openssh-5.8p1/monitor.c 2011-02-09 22:24:22.000000000 +0100 +@@ -180,6 +180,7 @@ int mm_answer_audit_event(int, Buffer *) + int mm_answer_audit_command(int, Buffer *); + int mm_answer_audit_unsupported_body(int, Buffer *); + int mm_answer_audit_kex_body(int, Buffer *); ++int mm_answer_audit_session_key_free_body(int, Buffer *); + #endif + + static Authctxt *authctxt; +@@ -230,6 +231,7 @@ struct mon_table mon_dispatch_proto20[] + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, + {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, + {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, ++ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, + #endif + #ifdef BSD_AUTH + {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, +@@ -268,6 +270,7 @@ struct mon_table mon_dispatch_postauth20 + {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, + {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, + {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, ++ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, + #endif + {0, 0, NULL} + }; +@@ -301,6 +304,7 @@ struct mon_table mon_dispatch_proto15[] + {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, + {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, + {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, ++ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, + #endif + {0, 0, NULL} + }; +@@ -314,6 +318,7 @@ struct mon_table mon_dispatch_postauth15 + {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, + {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, + {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, ++ {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, + #endif + {0, 0, NULL} + }; +@@ -2253,4 +2258,18 @@ mm_answer_audit_kex_body(int sock, Buffe + return 0; + } + ++int ++mm_answer_audit_session_key_free_body(int sock, Buffer *m) ++{ ++ int ctos; ++ ++ ctos = buffer_get_int(m); ++ ++ audit_session_key_free_body(ctos); ++ ++ buffer_clear(m); ++ ++ mm_request_send(sock, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, m); ++ return 0; ++} + #endif /* SSH_AUDIT_EVENTS */ +diff -up openssh-5.8p1/monitor.h.audit4 openssh-5.8p1/monitor.h +--- openssh-5.8p1/monitor.h.audit4 2011-02-09 22:24:22.000000000 +0100 ++++ openssh-5.8p1/monitor.h 2011-02-09 22:24:22.000000000 +0100 +@@ -68,6 +68,7 @@ enum monitor_reqtype { + MONITOR_REQ_JPAKE_CHECK_CONFIRM, MONITOR_ANS_JPAKE_CHECK_CONFIRM, + MONITOR_REQ_AUDIT_UNSUPPORTED, MONITOR_ANS_AUDIT_UNSUPPORTED, + MONITOR_REQ_AUDIT_KEX, MONITOR_ANS_AUDIT_KEX, ++ MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, + }; + + struct mm_master; +diff -up openssh-5.8p1/monitor_wrap.c.audit4 openssh-5.8p1/monitor_wrap.c +--- openssh-5.8p1/monitor_wrap.c.audit4 2011-02-09 22:24:22.000000000 +0100 ++++ openssh-5.8p1/monitor_wrap.c 2011-02-09 22:24:22.000000000 +0100 +@@ -1446,4 +1446,17 @@ mm_audit_kex_body(int ctos, char *cipher + + buffer_free(&m); + } ++ ++void ++mm_audit_session_key_free_body(int ctos) ++{ ++ Buffer m; ++ ++ buffer_init(&m); ++ buffer_put_int(&m, ctos); ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SESSION_KEY_FREE, &m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, ++ &m); ++ buffer_free(&m); ++} + #endif /* SSH_AUDIT_EVENTS */ +diff -up openssh-5.8p1/monitor_wrap.h.audit4 openssh-5.8p1/monitor_wrap.h +--- openssh-5.8p1/monitor_wrap.h.audit4 2011-02-09 22:24:22.000000000 +0100 ++++ openssh-5.8p1/monitor_wrap.h 2011-02-09 22:24:22.000000000 +0100 +@@ -76,6 +76,7 @@ void mm_audit_event(ssh_audit_event_t); + void mm_audit_run_command(const char *); + void mm_audit_unsupported_body(int); + void mm_audit_kex_body(int, char *, char *, char *); ++void mm_audit_session_key_free_body(int); + #endif + + struct Session; +diff -up openssh-5.8p1/packet.c.audit4 openssh-5.8p1/packet.c +--- openssh-5.8p1/packet.c.audit4 2010-11-24 00:46:37.000000000 +0100 ++++ openssh-5.8p1/packet.c 2011-02-09 22:24:22.000000000 +0100 +@@ -497,6 +497,7 @@ packet_close(void) + } + cipher_cleanup(&active_state->send_context); + cipher_cleanup(&active_state->receive_context); ++ audit_session_key_free(2); + } + + /* Sets remote side protocol flags. */ +@@ -756,6 +757,7 @@ set_newkeys(int mode) + } + if (active_state->newkeys[mode] != NULL) { + debug("set_newkeys: rekeying"); ++ audit_session_key_free(mode); + cipher_cleanup(cc); + enc = &active_state->newkeys[mode]->enc; + mac = &active_state->newkeys[mode]->mac; +@@ -1912,6 +1914,34 @@ packet_get_newkeys(int mode) + return (void *)active_state->newkeys[mode]; + } + ++static void ++packet_destroy_state(struct session_state *state) ++{ ++ if (state == NULL) ++ return; ++ ++ cipher_cleanup(&state->receive_context); ++ cipher_cleanup(&state->send_context); ++ ++ buffer_free(&state->input); ++ buffer_free(&state->output); ++ buffer_free(&state->outgoing_packet); ++ buffer_free(&state->incoming_packet); ++ buffer_free(&state->compression_buffer); ++ newkeys_destroy(state->newkeys[MODE_IN]); ++ newkeys_destroy(state->newkeys[MODE_OUT]); ++ mac_destroy(state->packet_discard_mac); ++// TAILQ_HEAD(, packet) outgoing; ++// memset(state, 0, sizeof(state)); ++} ++ ++void ++packet_destroy_all(void) ++{ ++ packet_destroy_state(active_state); ++ packet_destroy_state(backup_state); ++} ++ + /* + * Save the state for the real connection, and use a separate state when + * resuming a suspended connection. +@@ -1919,18 +1949,12 @@ packet_get_newkeys(int mode) + void + packet_backup_state(void) + { +- struct session_state *tmp; +- + close(active_state->connection_in); + active_state->connection_in = -1; + close(active_state->connection_out); + active_state->connection_out = -1; +- if (backup_state) +- tmp = backup_state; +- else +- tmp = alloc_session_state(); + backup_state = active_state; +- active_state = tmp; ++ active_state = alloc_session_state(); + } + + /* +@@ -1947,9 +1971,7 @@ packet_restore_state(void) + backup_state = active_state; + active_state = tmp; + active_state->connection_in = backup_state->connection_in; +- backup_state->connection_in = -1; + active_state->connection_out = backup_state->connection_out; +- backup_state->connection_out = -1; + len = buffer_len(&backup_state->input); + if (len > 0) { + buf = buffer_ptr(&backup_state->input); +@@ -1957,4 +1979,10 @@ packet_restore_state(void) + buffer_clear(&backup_state->input); + add_recv_bytes(len); + } ++ backup_state->connection_in = -1; ++ backup_state->connection_out = -1; ++ packet_destroy_state(backup_state); ++ xfree(backup_state); ++ backup_state = NULL; + } ++ +diff -up openssh-5.8p1/packet.h.audit4 openssh-5.8p1/packet.h +--- openssh-5.8p1/packet.h.audit4 2010-11-20 05:19:38.000000000 +0100 ++++ openssh-5.8p1/packet.h 2011-02-09 22:24:22.000000000 +0100 +@@ -125,4 +125,5 @@ void packet_restore_state(void); + void *packet_get_input(void); + void *packet_get_output(void); + ++void packet_destroy_all(void); + #endif /* PACKET_H */ +diff -up openssh-5.8p1/sshd.c.audit4 openssh-5.8p1/sshd.c +--- openssh-5.8p1/sshd.c.audit4 2011-02-09 22:24:22.000000000 +0100 ++++ openssh-5.8p1/sshd.c 2011-02-09 22:24:22.000000000 +0100 +@@ -663,6 +663,8 @@ privsep_preauth(Authctxt *authctxt) + return (0); + } + ++extern Newkeys *current_keys[]; ++ + static void + privsep_postauth(Authctxt *authctxt) + { +@@ -688,6 +690,10 @@ privsep_postauth(Authctxt *authctxt) + verbose("User child is on pid %ld", (long)pmonitor->m_pid); + close(pmonitor->m_recvfd); + buffer_clear(&loginmsg); ++ newkeys_destroy(current_keys[MODE_OUT]); ++ newkeys_destroy(current_keys[MODE_IN]); ++ packet_destroy_all(); ++ audit_session_key_free_body(2); + monitor_child_postauth(pmonitor); + + /* NEVERREACHED */ +@@ -1974,6 +1980,8 @@ main(int ac, char **av) + */ + if (use_privsep) { + mm_send_keystate(pmonitor); ++ packet_destroy_all(); ++ audit_session_key_free(2); + exit(0); + } + +@@ -2026,6 +2034,9 @@ main(int ac, char **av) + do_authenticated(authctxt); + + /* The connection has been terminated. */ ++ packet_destroy_all(); ++ audit_session_key_free(2); ++ + packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes); + packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes); + verbose("Transferred: sent %llu, received %llu bytes", diff --git a/openssh-5.8p1-audit5.patch b/openssh-5.8p1-audit5.patch new file mode 100644 index 0000000..17f9cfd --- /dev/null +++ b/openssh-5.8p1-audit5.patch @@ -0,0 +1,215 @@ +diff -up openssh-5.8p1/audit-bsm.c.audit5 openssh-5.8p1/audit-bsm.c +--- openssh-5.8p1/audit-bsm.c.audit5 2011-02-09 22:33:51.000000000 +0100 ++++ openssh-5.8p1/audit-bsm.c 2011-02-09 22:33:52.000000000 +0100 +@@ -401,4 +401,10 @@ audit_session_key_free_body(int ctos) + { + /* not implemented */ + } ++ ++void ++audit_destroy_sensitive_data(void) ++{ ++ /* not implemented */ ++} + #endif /* BSM */ +diff -up openssh-5.8p1/audit.c.audit5 openssh-5.8p1/audit.c +--- openssh-5.8p1/audit.c.audit5 2011-02-09 22:33:51.000000000 +0100 ++++ openssh-5.8p1/audit.c 2011-02-09 22:33:52.000000000 +0100 +@@ -268,5 +268,14 @@ audit_session_key_free_body(int ctos) + { + debug("audit session key discard euid %d direction %d", geteuid(), ctos); + } ++ ++/* ++ * This will be called on destroy private part of the server key ++ */ ++void ++audit_destroy_sensitive_data(void) ++{ ++ debug("audit destroy sensitive data euid %d", geteuid()); ++} + # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ + #endif /* SSH_AUDIT_EVENTS */ +diff -up openssh-5.8p1/audit.h.audit5 openssh-5.8p1/audit.h +--- openssh-5.8p1/audit.h.audit5 2011-02-09 22:33:51.000000000 +0100 ++++ openssh-5.8p1/audit.h 2011-02-09 22:33:52.000000000 +0100 +@@ -62,5 +62,6 @@ void audit_unsupported_body(int); + void audit_kex_body(int, char *, char *, char *); + void audit_session_key_free(int ctos); + void audit_session_key_free_body(int ctos); ++void audit_destroy_sensitive_data(void); + + #endif /* _SSH_AUDIT_H */ +diff -up openssh-5.8p1/audit-linux.c.audit5 openssh-5.8p1/audit-linux.c +--- openssh-5.8p1/audit-linux.c.audit5 2011-02-09 22:33:51.000000000 +0100 ++++ openssh-5.8p1/audit-linux.c 2011-02-09 22:33:52.000000000 +0100 +@@ -231,4 +231,26 @@ audit_session_key_free_body(int ctos) + error("cannot write into audit"); + } + ++void ++audit_destroy_sensitive_data(void) ++{ ++ char buf[AUDIT_LOG_SIZE]; ++ int audit_fd, audit_ok; ++ ++ snprintf(buf, sizeof(buf), "destroy kind=server direction=?"); ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno != EINVAL && errno != EPROTONOSUPPORT && ++ errno != EAFNOSUPPORT) ++ error("cannot open audit"); ++ return; ++ } ++ audit_ok = audit_log_acct_message(audit_fd, AUDIT_CRYPTO_KEY_USER, NULL, ++ buf, NULL, -1, NULL, get_remote_ipaddr(), NULL, 1); ++ audit_close(audit_fd); ++ /* do not abort if the error is EPERM and sshd is run as non root user */ ++ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) ++ error("cannot write into audit"); ++} ++ + #endif /* USE_LINUX_AUDIT */ +diff -up openssh-5.8p1/monitor.c.audit5 openssh-5.8p1/monitor.c +--- openssh-5.8p1/monitor.c.audit5 2011-02-09 22:33:52.000000000 +0100 ++++ openssh-5.8p1/monitor.c 2011-02-09 22:33:52.000000000 +0100 +@@ -181,6 +181,7 @@ int mm_answer_audit_command(int, Buffer + int mm_answer_audit_unsupported_body(int, Buffer *); + int mm_answer_audit_kex_body(int, Buffer *); + int mm_answer_audit_session_key_free_body(int, Buffer *); ++int mm_answer_audit_server_key_free(int, Buffer *); + #endif + + static Authctxt *authctxt; +@@ -232,6 +233,7 @@ struct mon_table mon_dispatch_proto20[] + {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, + {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, + {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, ++ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, + #endif + #ifdef BSD_AUTH + {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, +@@ -271,6 +273,7 @@ struct mon_table mon_dispatch_postauth20 + {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, + {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, + {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, ++ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, + #endif + {0, 0, NULL} + }; +@@ -305,6 +308,7 @@ struct mon_table mon_dispatch_proto15[] + {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, + {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, + {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, ++ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, + #endif + {0, 0, NULL} + }; +@@ -319,6 +323,7 @@ struct mon_table mon_dispatch_postauth15 + {MONITOR_REQ_AUDIT_UNSUPPORTED, MON_PERMIT, mm_answer_audit_unsupported_body}, + {MONITOR_REQ_AUDIT_KEX, MON_PERMIT, mm_answer_audit_kex_body}, + {MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MON_PERMIT, mm_answer_audit_session_key_free_body}, ++ {MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MON_PERMIT, mm_answer_audit_server_key_free}, + #endif + {0, 0, NULL} + }; +@@ -2272,4 +2277,15 @@ mm_answer_audit_session_key_free_body(in + mm_request_send(sock, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, m); + return 0; + } ++ ++int ++mm_answer_audit_server_key_free(int sock, Buffer *m) ++{ ++ audit_destroy_sensitive_data(); ++ ++ buffer_clear(m); ++ ++ mm_request_send(sock, MONITOR_ANS_AUDIT_SERVER_KEY_FREE, m); ++ return 0; ++} + #endif /* SSH_AUDIT_EVENTS */ +diff -up openssh-5.8p1/monitor.h.audit5 openssh-5.8p1/monitor.h +--- openssh-5.8p1/monitor.h.audit5 2011-02-09 22:33:52.000000000 +0100 ++++ openssh-5.8p1/monitor.h 2011-02-09 22:33:52.000000000 +0100 +@@ -69,6 +69,7 @@ enum monitor_reqtype { + MONITOR_REQ_AUDIT_UNSUPPORTED, MONITOR_ANS_AUDIT_UNSUPPORTED, + MONITOR_REQ_AUDIT_KEX, MONITOR_ANS_AUDIT_KEX, + MONITOR_REQ_AUDIT_SESSION_KEY_FREE, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, ++ MONITOR_REQ_AUDIT_SERVER_KEY_FREE, MONITOR_ANS_AUDIT_SERVER_KEY_FREE, + }; + + struct mm_master; +diff -up openssh-5.8p1/monitor_wrap.c.audit5 openssh-5.8p1/monitor_wrap.c +--- openssh-5.8p1/monitor_wrap.c.audit5 2011-02-09 22:33:52.000000000 +0100 ++++ openssh-5.8p1/monitor_wrap.c 2011-02-09 22:33:52.000000000 +0100 +@@ -1459,4 +1459,16 @@ mm_audit_session_key_free_body(int ctos) + &m); + buffer_free(&m); + } ++ ++void ++mm_audit_destroy_sensitive_data(void) ++{ ++ Buffer m; ++ ++ buffer_init(&m); ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SERVER_KEY_FREE, &m); ++ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_SERVER_KEY_FREE, ++ &m); ++ buffer_free(&m); ++} + #endif /* SSH_AUDIT_EVENTS */ +diff -up openssh-5.8p1/monitor_wrap.h.audit5 openssh-5.8p1/monitor_wrap.h +--- openssh-5.8p1/monitor_wrap.h.audit5 2011-02-09 22:33:52.000000000 +0100 ++++ openssh-5.8p1/monitor_wrap.h 2011-02-09 22:33:52.000000000 +0100 +@@ -77,6 +77,7 @@ void mm_audit_run_command(const char *); + void mm_audit_unsupported_body(int); + void mm_audit_kex_body(int, char *, char *, char *); + void mm_audit_session_key_free_body(int); ++void mm_audit_server_key_free_body(void); + #endif + + struct Session; +diff -up openssh-5.8p1/session.c.audit5 openssh-5.8p1/session.c +--- openssh-5.8p1/session.c.audit5 2010-12-01 02:02:59.000000000 +0100 ++++ openssh-5.8p1/session.c 2011-02-09 22:33:52.000000000 +0100 +@@ -1615,6 +1615,7 @@ do_child(Session *s, const char *command + + /* remove hostkey from the child's memory */ + destroy_sensitive_data(); ++ PRIVSEP(audit_destroy_sensitive_data()); + + /* Force a password change */ + if (s->authctxt->force_pwchange) { +diff -up openssh-5.8p1/sshd.c.audit5 openssh-5.8p1/sshd.c +--- openssh-5.8p1/sshd.c.audit5 2011-02-09 22:33:52.000000000 +0100 ++++ openssh-5.8p1/sshd.c 2011-02-09 22:33:52.000000000 +0100 +@@ -579,6 +579,7 @@ demote_sensitive_data(void) + } + /* Certs do not need demotion */ + } ++ audit_destroy_sensitive_data(); + + /* We do not clear ssh1_host key and cookie. XXX - Okay Niels? */ + } +@@ -2023,8 +2024,10 @@ main(int ac, char **av) + if (use_privsep) { + privsep_postauth(authctxt); + /* the monitor process [priv] will not return */ +- if (!compat20) ++ if (!compat20) { + destroy_sensitive_data(); ++ audit_destroy_sensitive_data(); ++ } + } + + packet_set_timeout(options.client_alive_interval, +@@ -2265,6 +2268,7 @@ do_ssh1_kex(void) + } + /* Destroy the private and public keys. No longer. */ + destroy_sensitive_data(); ++ audit_destroy_sensitive_data(); + + if (use_privsep) + mm_ssh1_session_id(session_id); diff --git a/openssh-5.8p1-authorized-keys-command.patch b/openssh-5.8p1-authorized-keys-command.patch new file mode 100644 index 0000000..356adfa --- /dev/null +++ b/openssh-5.8p1-authorized-keys-command.patch @@ -0,0 +1,447 @@ +diff -up openssh-5.8p1/auth2-pubkey.c.akc openssh-5.8p1/auth2-pubkey.c +--- openssh-5.8p1/auth2-pubkey.c.akc 2011-02-10 13:21:27.000000000 +0100 ++++ openssh-5.8p1/auth2-pubkey.c 2011-02-10 13:21:28.000000000 +0100 +@@ -27,6 +27,7 @@ + + #include + #include ++#include + + #include + #include +@@ -268,27 +269,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); + +@@ -381,8 +370,6 @@ user_key_allowed2(struct passwd *pw, Key + break; + } + } +- restore_uid(); +- fclose(f); + key_free(found); + if (!found_key) + debug2("key not found"); +@@ -444,13 +431,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 -1; ++ ++ /* 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.8p1/configure.ac.akc openssh-5.8p1/configure.ac +--- openssh-5.8p1/configure.ac.akc 2011-02-10 13:21:28.000000000 +0100 ++++ openssh-5.8p1/configure.ac 2011-02-10 13:21:28.000000000 +0100 +@@ -1422,6 +1422,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 \ +@@ -4325,6 +4337,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.8p1/servconf.c.akc openssh-5.8p1/servconf.c +--- openssh-5.8p1/servconf.c.akc 2011-02-10 13:21:28.000000000 +0100 ++++ openssh-5.8p1/servconf.c 2011-02-10 13:28:21.000000000 +0100 +@@ -134,6 +134,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; +@@ -331,6 +333,7 @@ typedef enum { + sZeroKnowledgePasswordAuthentication, sHostCertificate, + sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, + sKexAlgorithms, sIPQoS, ++ sAuthorizedKeysCommand, sAuthorizedKeysCommandRunAs, + sDeprecated, sUnsupported + } ServerOpCodes; + +@@ -456,6 +459,13 @@ static struct { + { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, + { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, + { "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 } + }; + +@@ -1406,6 +1416,20 @@ 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 (*activep && *charptr == NULL) ++ *charptr = xstrdup(arg); ++ break; ++ + case sDeprecated: + logit("%s line %d: Deprecated option %s", + filename, linenum, arg); +@@ -1499,6 +1523,8 @@ copy_set_server_options(ServerOptions *d + M_CP_INTOPT(gss_authentication); + M_CP_INTOPT(rsa_authentication); + M_CP_INTOPT(pubkey_authentication); ++ M_CP_STROPT(authorized_keys_command); ++ M_CP_STROPT(authorized_keys_command_runas); + M_CP_INTOPT(kerberos_authentication); + M_CP_INTOPT(hostbased_authentication); + M_CP_INTOPT(hostbased_uses_name_from_packet_only); +@@ -1753,6 +1779,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.8p1/servconf.h.akc openssh-5.8p1/servconf.h +--- openssh-5.8p1/servconf.h.akc 2011-02-10 13:21:28.000000000 +0100 ++++ openssh-5.8p1/servconf.h 2011-02-10 13:21:28.000000000 +0100 +@@ -161,6 +161,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; + + void initialize_server_options(ServerOptions *); +diff -up openssh-5.8p1/sshd_config.0.akc openssh-5.8p1/sshd_config.0 +--- openssh-5.8p1/sshd_config.0.akc 2011-02-10 13:21:28.000000000 +0100 ++++ openssh-5.8p1/sshd_config.0 2011-02-10 13:21:28.000000000 +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 +@@ -398,7 +415,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.8p1/sshd_config.5.akc openssh-5.8p1/sshd_config.5 +--- openssh-5.8p1/sshd_config.5.akc 2011-02-10 13:21:28.000000000 +0100 ++++ openssh-5.8p1/sshd_config.5 2011-02-10 13:21:28.000000000 +0100 +@@ -703,6 +703,8 @@ Available keywords are + .Cm AllowAgentForwarding , + .Cm AllowTcpForwarding , + .Cm AuthorizedKeysFile , ++.Cm AuthorizedKeysCommand , ++.Cm AuthorizedKeysCommandRunAs , + .Cm AuthorizedPrincipalsFile , + .Cm Banner , + .Cm ChrootDirectory , +@@ -715,6 +717,7 @@ Available keywords are + .Cm KerberosAuthentication , + .Cm MaxAuthTries , + .Cm MaxSessions , ++.Cm PubkeyAuthentication , + .Cm PasswordAuthentication , + .Cm PermitEmptyPasswords , + .Cm PermitOpen , +@@ -917,6 +920,20 @@ 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 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. ++.Dq + .It Cm RhostsRSAAuthentication + Specifies whether rhosts or /etc/hosts.equiv authentication together + with successful RSA host authentication is allowed. +diff -up openssh-5.8p1/sshd_config.akc openssh-5.8p1/sshd_config +--- openssh-5.8p1/sshd_config.akc 2011-02-10 13:21:28.000000000 +0100 ++++ openssh-5.8p1/sshd_config 2011-02-10 13:21:28.000000000 +0100 +@@ -46,6 +46,8 @@ SyslogFacility AUTHPRIV + #RSAAuthentication yes + #PubkeyAuthentication yes + #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 diff --git a/openssh-5.8p1-fips.patch b/openssh-5.8p1-fips.patch new file mode 100644 index 0000000..c1de68d --- /dev/null +++ b/openssh-5.8p1-fips.patch @@ -0,0 +1,734 @@ +diff -up openssh-5.8p1/audit.c.fips openssh-5.8p1/audit.c +--- openssh-5.8p1/audit.c.fips 2011-02-14 10:10:41.000000000 +0100 ++++ openssh-5.8p1/audit.c 2011-02-14 10:10:41.000000000 +0100 +@@ -124,7 +124,7 @@ audit_key(int type, int *rv, const Key * + "ssh-dsa", + "unknown" }; + +- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); ++ fp = key_fingerprint(key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); + switch(key->type) { + case KEY_RSA1: + case KEY_RSA: +diff -up openssh-5.8p1/auth2-pubkey.c.fips openssh-5.8p1/auth2-pubkey.c +--- openssh-5.8p1/auth2-pubkey.c.fips 2011-02-14 10:10:41.000000000 +0100 ++++ openssh-5.8p1/auth2-pubkey.c 2011-02-14 10:10:41.000000000 +0100 +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + + #include "xmalloc.h" + #include "ssh.h" +@@ -371,7 +372,7 @@ user_search_key_in_file(FILE *f, char *f + found_key = 1; + debug("matching key found: file %s, line %lu", + file, linenum); +- fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); ++ fp = key_fingerprint(found, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); + verbose("Found matching %s key: %s", + key_type(found), fp); + xfree(fp); +diff -up openssh-5.8p1/authfile.c.fips openssh-5.8p1/authfile.c +--- openssh-5.8p1/authfile.c.fips 2010-12-01 02:03:39.000000000 +0100 ++++ openssh-5.8p1/authfile.c 2011-02-14 10:10:41.000000000 +0100 +@@ -145,8 +145,14 @@ key_private_rsa1_to_blob(Key *key, Buffe + /* Allocate space for the private part of the key in the buffer. */ + cp = buffer_append_space(&encrypted, buffer_len(&buffer)); + +- cipher_set_key_string(&ciphercontext, cipher, passphrase, +- CIPHER_ENCRYPT); ++ if (cipher_set_key_string(&ciphercontext, cipher, passphrase, ++ CIPHER_ENCRYPT) < 0) { ++ error("cipher_set_key_string failed."); ++ buffer_free(&encrypted); ++ buffer_free(&buffer); ++ return 0; ++ } ++ + cipher_crypt(&ciphercontext, cp, + buffer_ptr(&buffer), buffer_len(&buffer)); + cipher_cleanup(&ciphercontext); +@@ -447,8 +453,13 @@ key_parse_private_rsa1(Buffer *blob, con + cp = buffer_append_space(&decrypted, buffer_len(blob)); + + /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */ +- cipher_set_key_string(&ciphercontext, cipher, passphrase, +- CIPHER_DECRYPT); ++ if (cipher_set_key_string(&ciphercontext, cipher, passphrase, ++ CIPHER_DECRYPT) < 0) { ++ error("cipher_set_key_string failed."); ++ buffer_free(&decrypted); ++ goto fail; ++ } ++ + cipher_crypt(&ciphercontext, cp, + buffer_ptr(blob), buffer_len(blob)); + cipher_cleanup(&ciphercontext); +diff -up openssh-5.8p1/auth-rsa.c.fips openssh-5.8p1/auth-rsa.c +--- openssh-5.8p1/auth-rsa.c.fips 2011-02-14 10:10:41.000000000 +0100 ++++ openssh-5.8p1/auth-rsa.c 2011-02-14 10:10:41.000000000 +0100 +@@ -119,7 +119,7 @@ auth_rsa_verify_response(Key *key, BIGNU + rv = timingsafe_bcmp(response, mdbuf, 16) == 0; + + #ifdef SSH_AUDIT_EVENTS +- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); ++ fp = key_fingerprint(key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); + if (audit_keyusage(1, "ssh-rsa1", RSA_size(key->rsa), fp, rv) == 0) { + debug("unsuccessful audit"); + rv = 0; +diff -up openssh-5.8p1/cipher.c.fips openssh-5.8p1/cipher.c +--- openssh-5.8p1/cipher.c.fips 2011-02-14 10:10:41.000000000 +0100 ++++ openssh-5.8p1/cipher.c 2011-02-14 10:10:41.000000000 +0100 +@@ -40,6 +40,7 @@ + #include + + #include ++#include + + #include + #include +@@ -85,6 +86,22 @@ struct Cipher ciphers[] = { + { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL } + }; + ++struct Cipher fips_ciphers[] = { ++ { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, EVP_enc_null }, ++ { "3des", SSH_CIPHER_3DES, 8, 16, 0, 1, evp_ssh1_3des }, ++ ++ { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 1, EVP_des_ede3_cbc }, ++ { "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 1, EVP_aes_128_cbc }, ++ { "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 1, EVP_aes_192_cbc }, ++ { "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc }, ++ { "rijndael-cbc@lysator.liu.se", ++ SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc }, ++ { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, evp_aes_128_ctr }, ++ { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, evp_aes_128_ctr }, ++ { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, evp_aes_128_ctr }, ++ { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL } ++}; ++ + /*--*/ + + u_int +@@ -127,7 +144,7 @@ Cipher * + cipher_by_name(const char *name) + { + Cipher *c; +- for (c = ciphers; c->name != NULL; c++) ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) + if (strcmp(c->name, name) == 0) + return c; + return NULL; +@@ -137,7 +154,7 @@ Cipher * + cipher_by_number(int id) + { + Cipher *c; +- for (c = ciphers; c->name != NULL; c++) ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) + if (c->number == id) + return c; + return NULL; +@@ -181,7 +198,7 @@ cipher_number(const char *name) + Cipher *c; + if (name == NULL) + return -1; +- for (c = ciphers; c->name != NULL; c++) ++ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) + if (strcasecmp(c->name, name) == 0) + return c->number; + return -1; +@@ -288,14 +305,15 @@ cipher_cleanup(CipherContext *cc) + * passphrase and using the resulting 16 bytes as the key. + */ + +-void ++int + cipher_set_key_string(CipherContext *cc, Cipher *cipher, + const char *passphrase, int do_encrypt) + { + MD5_CTX md; + u_char digest[16]; + +- MD5_Init(&md); ++ if (MD5_Init(&md) <= 0) ++ return -1; + MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase)); + MD5_Final(digest, &md); + +@@ -303,6 +321,7 @@ cipher_set_key_string(CipherContext *cc, + + memset(digest, 0, sizeof(digest)); + memset(&md, 0, sizeof(md)); ++ return 0; + } + + /* +diff -up openssh-5.8p1/cipher-ctr.c.fips openssh-5.8p1/cipher-ctr.c +--- openssh-5.8p1/cipher-ctr.c.fips 2010-10-07 13:06:42.000000000 +0200 ++++ openssh-5.8p1/cipher-ctr.c 2011-02-14 10:10:41.000000000 +0100 +@@ -140,7 +140,8 @@ evp_aes_128_ctr(void) + aes_ctr.do_cipher = ssh_aes_ctr; + #ifndef SSH_OLD_EVP + aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | +- EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; ++ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV | ++ EVP_CIPH_FLAG_FIPS; + #endif + return (&aes_ctr); + } +diff -up openssh-5.8p1/cipher.h.fips openssh-5.8p1/cipher.h +--- openssh-5.8p1/cipher.h.fips 2011-02-14 10:10:41.000000000 +0100 ++++ openssh-5.8p1/cipher.h 2011-02-14 10:10:41.000000000 +0100 +@@ -87,7 +87,7 @@ void cipher_init(CipherContext *, Ciphe + const u_char *, u_int, int); + void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int); + void cipher_cleanup(CipherContext *); +-void cipher_set_key_string(CipherContext *, Cipher *, const char *, int); ++int cipher_set_key_string(CipherContext *, Cipher *, const char *, int); + u_int cipher_blocksize(const Cipher *); + u_int cipher_keylen(const Cipher *); + u_int cipher_is_cbc(const Cipher *); +diff -up openssh-5.8p1/mac.c.fips openssh-5.8p1/mac.c +--- openssh-5.8p1/mac.c.fips 2011-02-14 10:10:41.000000000 +0100 ++++ openssh-5.8p1/mac.c 2011-02-14 10:10:41.000000000 +0100 +@@ -28,6 +28,7 @@ + #include + + #include ++#include + + #include + #include +@@ -47,14 +48,14 @@ + #define SSH_EVP 1 /* OpenSSL EVP-based MAC */ + #define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */ + +-struct { ++struct Macs { + char *name; + int type; + const EVP_MD * (*mdfunc)(void); + int truncatebits; /* truncate digest if != 0 */ + int key_len; /* just for UMAC */ + int len; /* just for UMAC */ +-} macs[] = { ++} all_macs[] = { + { "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1, -1 }, + { "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, -1, -1 }, + { "hmac-md5", SSH_EVP, EVP_md5, 0, -1, -1 }, +@@ -65,9 +66,15 @@ struct { + { NULL, 0, NULL, 0, -1, -1 } + }; + ++struct Macs fips_macs[] = { ++ { "hmac-sha1", SSH_EVP, EVP_sha1, 0, -1, -1 }, ++ { NULL, 0, NULL, 0, -1, -1 } ++}; ++ + static void + mac_setup_by_id(Mac *mac, int which) + { ++ struct Macs *macs = FIPS_mode() ? fips_macs : all_macs; + int evp_len; + mac->type = macs[which].type; + if (mac->type == SSH_EVP) { +@@ -88,6 +95,7 @@ int + mac_setup(Mac *mac, char *name) + { + int i; ++ struct Macs *macs = FIPS_mode() ? fips_macs : all_macs; + + for (i = 0; macs[i].name; i++) { + if (strcmp(name, macs[i].name) == 0) { +diff -up openssh-5.8p1/Makefile.in.fips openssh-5.8p1/Makefile.in +--- openssh-5.8p1/Makefile.in.fips 2011-02-14 10:10:41.000000000 +0100 ++++ openssh-5.8p1/Makefile.in 2011-02-14 10:10:41.000000000 +0100 +@@ -145,25 +145,25 @@ libssh.a: $(LIBSSH_OBJS) + $(RANLIB) $@ + + ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) +- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS) ++ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHLIBS) $(LIBS) + + sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) +- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) ++ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHDLIBS) $(LIBS) + + scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o + $(LD) -o $@ scp.o progressmeter.o bufaux.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + + ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o +- $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o +- $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o +- $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o roaming_dummy.o readconf.o +- $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ $(LD) -o $@ ssh-keysign.o readconf.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o + $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) +@@ -172,7 +172,7 @@ ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) l + $(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) + + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o roaming_dummy.o +- $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) ++ $(LD) -o $@ ssh-keyscan.o roaming_dummy.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS) + + sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o + $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) +diff -up openssh-5.8p1/myproposal.h.fips openssh-5.8p1/myproposal.h +--- openssh-5.8p1/myproposal.h.fips 2011-01-13 12:00:22.000000000 +0100 ++++ openssh-5.8p1/myproposal.h 2011-02-14 10:10:41.000000000 +0100 +@@ -81,7 +81,12 @@ + "hmac-sha1-96,hmac-md5-96" + #define KEX_DEFAULT_COMP "none,zlib@openssh.com,zlib" + #define KEX_DEFAULT_LANG "" +- ++#define KEX_FIPS_ENCRYPT \ ++ "aes128-ctr,aes192-ctr,aes256-ctr," \ ++ "aes128-cbc,3des-cbc," \ ++ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se" ++#define KEX_FIPS_MAC \ ++ "hmac-sha1" + + static char *myproposal[PROPOSAL_MAX] = { + KEX_DEFAULT_KEX, +diff -up openssh-5.8p1/openbsd-compat/bsd-arc4random.c.fips openssh-5.8p1/openbsd-compat/bsd-arc4random.c +--- openssh-5.8p1/openbsd-compat/bsd-arc4random.c.fips 2010-03-25 22:52:02.000000000 +0100 ++++ openssh-5.8p1/openbsd-compat/bsd-arc4random.c 2011-02-14 10:10:41.000000000 +0100 +@@ -39,6 +39,7 @@ + static int rc4_ready = 0; + static RC4_KEY rc4; + ++#if 0 + unsigned int + arc4random(void) + { +@@ -82,6 +83,32 @@ arc4random_stir(void) + + rc4_ready = REKEY_BYTES; + } ++#else ++unsigned int ++arc4random(void) ++{ ++ unsigned int r = 0; ++ void *rp = &r; ++ ++ if (!rc4_ready) { ++ arc4random_stir(); ++ } ++ RAND_bytes(rp, sizeof(r)); ++ ++ return(r); ++} ++ ++void ++arc4random_stir(void) ++{ ++ unsigned char rand_buf[SEED_SIZE]; ++ ++ if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0) ++ fatal("Couldn't obtain random bytes (error %ld)", ++ ERR_get_error()); ++ rc4_ready = 1; ++} ++#endif + #endif /* !HAVE_ARC4RANDOM */ + + #ifndef HAVE_ARC4RANDOM_BUF +diff -up openssh-5.8p1/ssh-add.c.fips openssh-5.8p1/ssh-add.c +--- openssh-5.8p1/ssh-add.c.fips 2010-11-11 04:17:02.000000000 +0100 ++++ openssh-5.8p1/ssh-add.c 2011-02-14 10:10:41.000000000 +0100 +@@ -42,6 +42,7 @@ + #include + + #include ++#include + #include "openbsd-compat/openssl-compat.h" + + #include +@@ -280,7 +281,7 @@ list_identities(AuthenticationConnection + key = ssh_get_next_identity(ac, &comment, version)) { + had_identities = 1; + if (do_fp) { +- fp = key_fingerprint(key, SSH_FP_MD5, ++ fp = key_fingerprint(key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, + SSH_FP_HEX); + printf("%d %s %s (%s)\n", + key_size(key), fp, comment, key_type(key)); +diff -up openssh-5.8p1/ssh-agent.c.fips openssh-5.8p1/ssh-agent.c +--- openssh-5.8p1/ssh-agent.c.fips 2010-12-01 01:50:35.000000000 +0100 ++++ openssh-5.8p1/ssh-agent.c 2011-02-14 10:10:41.000000000 +0100 +@@ -51,6 +51,7 @@ + + #include + #include ++#include + #include "openbsd-compat/openssl-compat.h" + + #include +@@ -199,9 +200,9 @@ confirm_key(Identity *id) + char *p; + int ret = -1; + +- p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); +- if (ask_permission("Allow use of key %s?\nKey fingerprint %s.", +- id->comment, p)) ++ p = key_fingerprint(id->key, FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); ++ if (ask_permission("Allow use of key %s?\nKey %sfingerprint %s.", ++ id->comment, FIPS_mode() ? "SHA1 " : "", p)) + ret = 0; + xfree(p); + +diff -up openssh-5.8p1/ssh.c.fips openssh-5.8p1/ssh.c +--- openssh-5.8p1/ssh.c.fips 2011-02-04 01:42:15.000000000 +0100 ++++ openssh-5.8p1/ssh.c 2011-02-14 10:10:41.000000000 +0100 +@@ -73,6 +73,8 @@ + + #include + #include ++#include ++#include + #include "openbsd-compat/openssl-compat.h" + #include "openbsd-compat/sys-queue.h" + +@@ -234,6 +236,10 @@ main(int ac, char **av) + sanitise_stdfd(); + + __progname = ssh_get_progname(av[0]); ++ SSLeay_add_all_algorithms(); ++ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) { ++ fatal("FIPS integrity verification test failed."); ++ } + init_rng(); + + /* +@@ -300,6 +306,9 @@ main(int ac, char **av) + "ACD:F:I:KL:MNO:PR:S:TVw:W:XYy")) != -1) { + switch (opt) { + case '1': ++ if (FIPS_mode()) { ++ fatal("Protocol 1 not allowed in the FIPS mode."); ++ } + options.protocol = SSH_PROTO_1; + break; + case '2': +@@ -598,7 +607,6 @@ main(int ac, char **av) + if (!host) + usage(); + +- OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + /* Initialize the command to execute on remote host. */ +@@ -684,6 +692,10 @@ main(int ac, char **av) + + seed_rng(); + ++ if (FIPS_mode()) { ++ logit("FIPS mode initialized"); ++ } ++ + if (options.user == NULL) + options.user = xstrdup(pw->pw_name); + +@@ -753,6 +765,12 @@ main(int ac, char **av) + + timeout_ms = options.connection_timeout * 1000; + ++ if (FIPS_mode()) { ++ options.protocol &= SSH_PROTO_2; ++ if (options.protocol == 0) ++ fatal("Protocol 2 disabled by configuration but required in the FIPS mode."); ++ } ++ + /* Open a connection to the remote host. */ + if (ssh_connect(host, &hostaddr, options.port, + options.address_family, options.connection_attempts, &timeout_ms, +diff -up openssh-5.8p1/sshconnect2.c.fips openssh-5.8p1/sshconnect2.c +--- openssh-5.8p1/sshconnect2.c.fips 2010-12-01 02:21:51.000000000 +0100 ++++ openssh-5.8p1/sshconnect2.c 2011-02-14 10:10:41.000000000 +0100 +@@ -44,6 +44,8 @@ + #include + #endif + ++#include ++ + #include "openbsd-compat/sys-queue.h" + + #include "xmalloc.h" +@@ -169,6 +171,10 @@ ssh_kex2(char *host, struct sockaddr *ho + if (options.ciphers != NULL) { + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; ++ } else if (FIPS_mode()) { ++ myproposal[PROPOSAL_ENC_ALGS_CTOS] = ++ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT; ++ + } + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); +@@ -184,7 +190,11 @@ ssh_kex2(char *host, struct sockaddr *ho + if (options.macs != NULL) { + myproposal[PROPOSAL_MAC_ALGS_CTOS] = + myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; ++ } else if (FIPS_mode()) { ++ myproposal[PROPOSAL_MAC_ALGS_CTOS] = ++ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC; + } ++ + if (options.hostkeyalgorithms != NULL) + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = + options.hostkeyalgorithms; +@@ -590,8 +600,8 @@ input_userauth_pk_ok(int type, u_int32_t + key->type, pktype); + goto done; + } +- fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); +- debug2("input_userauth_pk_ok: fp %s", fp); ++ fp = key_fingerprint(key, SSH_FP_SHA1, SSH_FP_HEX); ++ debug2("input_userauth_pk_ok: SHA1 fp %s", fp); + xfree(fp); + + /* +diff -up openssh-5.8p1/sshconnect.c.fips openssh-5.8p1/sshconnect.c +--- openssh-5.8p1/sshconnect.c.fips 2011-01-16 13:17:59.000000000 +0100 ++++ openssh-5.8p1/sshconnect.c 2011-02-14 10:18:14.000000000 +0100 +@@ -41,6 +41,8 @@ + #include + #include + ++#include ++ + #include "xmalloc.h" + #include "key.h" + #include "hostfile.h" +@@ -705,6 +707,7 @@ check_host_key(char *hostname, struct so + int len, cancelled_forwarding = 0; + struct hostkeys *host_hostkeys, *ip_hostkeys; + const struct hostkey_entry *host_found, *ip_found; ++ int fips_on = FIPS_mode(); + + /* + * Force accepting of the host key for loopback/localhost. The +@@ -798,10 +801,10 @@ check_host_key(char *hostname, struct so + "key for IP address '%.128s' to the list " + "of known hosts.", type, ip); + } else if (options.visual_host_key) { +- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); +- ra = key_fingerprint(host_key, SSH_FP_MD5, ++ fp = key_fingerprint(host_key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); ++ ra = key_fingerprint(host_key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, + SSH_FP_RANDOMART); +- logit("Host key fingerprint is %s\n%s\n", fp, ra); ++ logit("Host key %sfingerprint is %s\n%s\n", fips_on ? "SHA1 " : "", fp, ra); + xfree(ra); + xfree(fp); + } +@@ -830,6 +833,7 @@ check_host_key(char *hostname, struct so + goto fail; + } else if (options.strict_host_key_checking == 2) { + char msg1[1024], msg2[1024]; ++ int fips_on = FIPS_mode(); + + if (show_other_keys(host_hostkeys, host_key)) + snprintf(msg1, sizeof(msg1), +@@ -838,8 +842,8 @@ check_host_key(char *hostname, struct so + else + snprintf(msg1, sizeof(msg1), "."); + /* The default */ +- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); +- ra = key_fingerprint(host_key, SSH_FP_MD5, ++ fp = key_fingerprint(host_key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); ++ ra = key_fingerprint(host_key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, + SSH_FP_RANDOMART); + msg2[0] = '\0'; + if (options.verify_host_key_dns) { +@@ -855,10 +859,10 @@ check_host_key(char *hostname, struct so + snprintf(msg, sizeof(msg), + "The authenticity of host '%.200s (%s)' can't be " + "established%s\n" +- "%s key fingerprint is %s.%s%s\n%s" ++ "%s key %sfingerprint is %s.%s%s\n%s" + "Are you sure you want to continue connecting " + "(yes/no)? ", +- host, ip, msg1, type, fp, ++ host, ip, msg1, type, fips_on ? "SHA1 " : "", fp, + options.visual_host_key ? "\n" : "", + options.visual_host_key ? ra : "", + msg2); +@@ -1208,20 +1212,21 @@ show_other_keys(struct hostkeys *hostkey + int i, ret = 0; + char *fp, *ra; + const struct hostkey_entry *found; ++ int fips_on = FIPS_mode(); + + for (i = 0; type[i] != -1; i++) { + if (type[i] == key->type) + continue; + if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found)) + continue; +- fp = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_HEX); +- ra = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_RANDOMART); ++ fp = key_fingerprint(found->key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); ++ ra = key_fingerprint(found->key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_RANDOMART); + logit("WARNING: %s key found for host %s\n" + "in %s:%lu\n" +- "%s key fingerprint %s.", ++ "%s key %sfingerprint %s.\n%s\n", + key_type(found->key), + found->host, found->file, found->line, +- key_type(found->key), fp); ++ key_type(found), fips_on ? "SHA1 ":"", fp, ra); + if (options.visual_host_key) + logit("%s", ra); + xfree(ra); +@@ -1235,8 +1240,9 @@ static void + warn_changed_key(Key *host_key) + { + char *fp; ++ int fips_on = FIPS_mode(); + +- fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); ++ fp = key_fingerprint(host_key, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); + + error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); + error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @"); +@@ -1244,8 +1250,8 @@ warn_changed_key(Key *host_key) + error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!"); + error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!"); + error("It is also possible that a host key has just been changed."); +- error("The fingerprint for the %s key sent by the remote host is\n%s.", +- key_type(host_key), fp); ++ error("The %sfingerprint for the %s key sent by the remote host is\n%s.", ++ fips_on ? "SHA1 ":"", key_type(host_key), fp); + error("Please contact your system administrator."); + + xfree(fp); +diff -up openssh-5.8p1/sshd.c.fips openssh-5.8p1/sshd.c +--- openssh-5.8p1/sshd.c.fips 2011-02-14 10:10:41.000000000 +0100 ++++ openssh-5.8p1/sshd.c 2011-02-14 10:10:41.000000000 +0100 +@@ -76,6 +76,8 @@ + #include + #include + #include ++#include ++#include + #include "openbsd-compat/openssl-compat.h" + + #ifdef HAVE_SECUREWARE +@@ -1314,6 +1316,12 @@ main(int ac, char **av) + (void)set_auth_parameters(ac, av); + #endif + __progname = ssh_get_progname(av[0]); ++ ++ SSLeay_add_all_algorithms(); ++ if (FIPS_mode() && !FIPSCHECK_verify(NULL, NULL)) { ++ fatal("FIPS integrity verification test failed."); ++ } ++ + init_rng(); + + /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ +@@ -1475,8 +1483,6 @@ main(int ac, char **av) + else + closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); + +- OpenSSL_add_all_algorithms(); +- + /* + * Force logging to stderr until we have loaded the private host + * key (unless started from inetd) +@@ -1595,6 +1601,10 @@ main(int ac, char **av) + debug("private host key: #%d type %d %s", i, key->type, + key_type(key)); + } ++ if ((options.protocol & SSH_PROTO_1) && FIPS_mode()) { ++ logit("Disabling protocol version 1. Not allowed in the FIPS mode."); ++ options.protocol &= ~SSH_PROTO_1; ++ } + if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { + logit("Disabling protocol version 1. Could not load host key"); + options.protocol &= ~SSH_PROTO_1; +@@ -1759,6 +1769,10 @@ main(int ac, char **av) + /* Initialize the random number generator. */ + arc4random_stir(); + ++ if (FIPS_mode()) { ++ logit("FIPS mode initialized"); ++ } ++ + /* Chdir to the root directory so that the current disk can be + unmounted if desired. */ + chdir("/"); +@@ -2305,6 +2319,9 @@ do_ssh2_kex(void) + if (options.ciphers != NULL) { + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers; ++ } else if (FIPS_mode()) { ++ myproposal[PROPOSAL_ENC_ALGS_CTOS] = ++ myproposal[PROPOSAL_ENC_ALGS_STOC] = KEX_FIPS_ENCRYPT; + } + myproposal[PROPOSAL_ENC_ALGS_CTOS] = + compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]); +@@ -2314,6 +2331,9 @@ do_ssh2_kex(void) + if (options.macs != NULL) { + myproposal[PROPOSAL_MAC_ALGS_CTOS] = + myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; ++ } else if (FIPS_mode()) { ++ myproposal[PROPOSAL_MAC_ALGS_CTOS] = ++ myproposal[PROPOSAL_MAC_ALGS_STOC] = KEX_FIPS_MAC; + } + if (options.compression == COMP_NONE) { + myproposal[PROPOSAL_COMP_ALGS_CTOS] = +diff -up openssh-5.8p1/ssh-keygen.c.fips openssh-5.8p1/ssh-keygen.c +--- openssh-5.8p1/ssh-keygen.c.fips 2011-02-14 10:10:41.000000000 +0100 ++++ openssh-5.8p1/ssh-keygen.c 2011-02-14 10:10:41.000000000 +0100 +@@ -21,6 +21,7 @@ + + #include + #include ++#include + #include "openbsd-compat/openssl-compat.h" + + #include +@@ -721,7 +722,7 @@ do_fingerprint(struct passwd *pw) + enum fp_type fptype; + struct stat st; + +- fptype = print_bubblebabble ? SSH_FP_SHA1 : SSH_FP_MD5; ++ fptype = print_bubblebabble ? SSH_FP_SHA1 : FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5; + rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_HEX; + + if (!have_identity) +@@ -2253,14 +2254,15 @@ passphrase_again: + fclose(f); + + if (!quiet) { +- char *fp = key_fingerprint(public, SSH_FP_MD5, SSH_FP_HEX); +- char *ra = key_fingerprint(public, SSH_FP_MD5, ++ int fips_on = FIPS_mode(); ++ char *fp = key_fingerprint(public, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, SSH_FP_HEX); ++ char *ra = key_fingerprint(public, fips_on ? SSH_FP_SHA1 : SSH_FP_MD5, + SSH_FP_RANDOMART); + printf("Your public key has been saved in %s.\n", + identity_file); +- printf("The key fingerprint is:\n"); ++ printf("The key %sfingerprint is:\n", fips_on ? "SHA1 " : ""); + printf("%s %s\n", fp, comment); +- printf("The key's randomart image is:\n"); ++ printf("The key's %srandomart image is:\n", fips_on ? "SHA1 " :""); + printf("%s\n", ra); + xfree(ra); + xfree(fp); diff --git a/openssh-5.8p1-gssapi-canohost.patch b/openssh-5.8p1-gssapi-canohost.patch new file mode 100644 index 0000000..a8e02fb --- /dev/null +++ b/openssh-5.8p1-gssapi-canohost.patch @@ -0,0 +1,24 @@ +diff -up openssh-5.8p1/sshconnect2.c.canohost openssh-5.8p1/sshconnect2.c +--- openssh-5.8p1/sshconnect2.c.canohost 2011-02-14 15:15:15.000000000 +0100 ++++ openssh-5.8p1/sshconnect2.c 2011-02-14 15:21:45.000000000 +0100 +@@ -697,14 +697,17 @@ userauth_gssapi(Authctxt *authctxt) + static u_int mech = 0; + OM_uint32 min; + int ok = 0; +- const char *gss_host; ++ const char *gss_host = NULL; + + 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; ++ else { ++ gss_host = get_canonical_hostname(1); ++ if ( strcmp( gss_host, "UNKNOWN" ) == 0 ) ++ gss_host = authctxt->host; ++ } + + /* Try one GSSAPI method at a time, rather than sending them all at + * once. */ diff --git a/openssh-5.8p1-gsskex.patch b/openssh-5.8p1-gsskex.patch new file mode 100644 index 0000000..ca456aa --- /dev/null +++ b/openssh-5.8p1-gsskex.patch @@ -0,0 +1,2996 @@ +diff -up openssh-5.8p1/auth2.c.gsskex openssh-5.8p1/auth2.c +--- openssh-5.8p1/auth2.c.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/auth2.c 2011-02-14 14:47:02.000000000 +0100 +@@ -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 +@@ -289,6 +291,7 @@ input_userauth_request(int type, u_int32 + #endif + + authctxt->postponed = 0; ++ authctxt->server_caused_failure = 0; + + /* try to authenticate user */ + m = authmethod_lookup(method); +@@ -361,7 +364,8 @@ userauth_finish(Authctxt *authctxt, int + } else { + + /* Allow initial try of "none" auth without failure penalty */ +- if (authctxt->attempt > 1 || strcmp(method, "none") != 0) ++ if (!authctxt->server_caused_failure && ++ (authctxt->attempt > 1 || strcmp(method, "none") != 0)) + authctxt->failures++; + if (authctxt->failures >= options.max_authtries) { + #ifdef SSH_AUDIT_EVENTS +diff -up openssh-5.8p1/auth2-gss.c.gsskex openssh-5.8p1/auth2-gss.c +--- openssh-5.8p1/auth2-gss.c.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/auth2-gss.c 2011-02-14 14:47:02.000000000 +0100 +@@ -1,7 +1,7 @@ + /* $OpenBSD: auth2-gss.c,v 1.16 2007/10/29 00:52:45 dtucker 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 +@@ -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) +@@ -102,6 +136,7 @@ userauth_gssapi(Authctxt *authctxt) + + if (!present) { + xfree(doid); ++ authctxt->server_caused_failure = 1; + return (0); + } + +@@ -109,6 +144,7 @@ userauth_gssapi(Authctxt *authctxt) + if (ctxt != NULL) + ssh_gssapi_delete_ctx(&ctxt); + xfree(doid); ++ authctxt->server_caused_failure = 1; + return (0); + } + +@@ -242,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); +@@ -284,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"); + +@@ -301,6 +339,12 @@ input_gssapi_mic(int type, u_int32_t ple + userauth_finish(authctxt, authenticated, "gssapi-with-mic"); + } + ++Authmethod method_gsskeyex = { ++ "gssapi-keyex", ++ userauth_gsskeyex, ++ &options.gss_authentication ++}; ++ + Authmethod method_gssapi = { + "gssapi-with-mic", + userauth_gssapi, +diff -up openssh-5.8p1/auth.h.gsskex openssh-5.8p1/auth.h +--- openssh-5.8p1/auth.h.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/auth.h 2011-02-14 14:47:02.000000000 +0100 +@@ -53,6 +53,7 @@ struct Authctxt { + int valid; /* user exists and is allowed to login */ + int attempt; + int failures; ++ int server_caused_failure; + int force_pwchange; + char *user; /* username sent by the client */ + char *service; +diff -up openssh-5.8p1/auth-krb5.c.gsskex openssh-5.8p1/auth-krb5.c +--- openssh-5.8p1/auth-krb5.c.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/auth-krb5.c 2011-02-14 14:47:02.000000000 +0100 +@@ -184,8 +184,13 @@ auth_krb5_password(Authctxt *authctxt, c + + len = strlen(authctxt->krb5_ticket_file) + 6; + authctxt->krb5_ccname = xmalloc(len); ++#ifdef USE_CCAPI ++ snprintf(authctxt->krb5_ccname, len, "API:%s", ++ authctxt->krb5_ticket_file); ++#else + snprintf(authctxt->krb5_ccname, len, "FILE:%s", + authctxt->krb5_ticket_file); ++#endif + + #ifdef USE_PAM + if (options.use_pam) +@@ -240,15 +245,22 @@ 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[] = "FILE:/tmp/krb5cc_%d_XXXXXXXXXX"; ++ int tmpfd; ++#endif + + ret = snprintf(ccname, sizeof(ccname), +- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); ++ cctemplate, geteuid()); + if (ret < 0 || (size_t)ret >= sizeof(ccname)) + return ENOMEM; + ++#ifndef USE_CCAPI + old_umask = umask(0177); + tmpfd = mkstemp(ccname + strlen("FILE:")); + umask(old_umask); +@@ -263,6 +275,7 @@ ssh_krb5_cc_gen(krb5_context ctx, krb5_c + return errno; + } + close(tmpfd); ++#endif + + return (krb5_cc_resolve(ctx, ccname, ccache)); + } +diff -up openssh-5.8p1/ChangeLog.gssapi.gsskex openssh-5.8p1/ChangeLog.gssapi +--- openssh-5.8p1/ChangeLog.gssapi.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/ChangeLog.gssapi 2011-02-14 14:47:02.000000000 +0100 +@@ -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-5.8p1/clientloop.c.gsskex openssh-5.8p1/clientloop.c +--- openssh-5.8p1/clientloop.c.gsskex 2011-01-16 13:18:35.000000000 +0100 ++++ openssh-5.8p1/clientloop.c 2011-02-14 14:47:02.000000000 +0100 +@@ -111,6 +111,10 @@ + #include "msg.h" + #include "roaming.h" + ++#ifdef GSSAPI ++#include "ssh-gss.h" ++#endif ++ + /* import options */ + extern Options options; + +@@ -1483,6 +1487,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-5.8p1/configure.ac.gsskex openssh-5.8p1/configure.ac +--- openssh-5.8p1/configure.ac.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/configure.ac 2011-02-14 14:47:02.000000000 +0100 +@@ -514,6 +514,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-5.8p1/gss-genr.c.gsskex openssh-5.8p1/gss-genr.c +--- openssh-5.8p1/gss-genr.c.gsskex 2009-06-22 08:11:07.000000000 +0200 ++++ openssh-5.8p1/gss-genr.c 2011-02-14 14:47:02.000000000 +0100 +@@ -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-5.8p1/gss-serv.c.gsskex openssh-5.8p1/gss-serv.c +--- openssh-5.8p1/gss-serv.c.gsskex 2008-05-19 07:05:07.000000000 +0200 ++++ openssh-5.8p1/gss-serv.c 2011-02-14 14:47:02.000000000 +0100 +@@ -1,7 +1,7 @@ + /* $OpenBSD: gss-serv.c,v 1.22 2008/05/08 12:02:23 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 +@@ -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, +@@ -247,8 +284,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); ++ } ++ ++ ctx->major = gss_compare_name(&ctx->minor, client->name, ++ new_name, &equal); + +- gss_buffer_desc ename; ++ 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; + +@@ -263,6 +340,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); +@@ -280,6 +364,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; +@@ -327,7 +413,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; + +@@ -337,9 +423,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); +@@ -352,14 +440,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-5.8p1/gss-serv-krb5.c.gsskex openssh-5.8p1/gss-serv-krb5.c +--- openssh-5.8p1/gss-serv-krb5.c.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/gss-serv-krb5.c 2011-02-14 14:47:02.000000000 +0100 +@@ -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 +@@ -121,6 +121,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"); +@@ -169,11 +170,16 @@ 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, "FILE:%s", new_ccname); ++ client->store.filename = xstrdup(new_ccname); ++#endif + + #ifdef USE_PAM + if (options.use_pam) +@@ -185,6 +191,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", +@@ -192,7 +263,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-5.8p1/kex.c.gsskex openssh-5.8p1/kex.c +--- openssh-5.8p1/kex.c.gsskex 2011-02-14 14:47:01.000000000 +0100 ++++ openssh-5.8p1/kex.c 2011-02-14 15:09:38.000000000 +0100 +@@ -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-5.8p1/kexgssc.c.gsskex openssh-5.8p1/kexgssc.c +--- openssh-5.8p1/kexgssc.c.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/kexgssc.c 2011-02-14 14:47:02.000000000 +0100 +@@ -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 (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-5.8p1/kexgsss.c.gsskex openssh-5.8p1/kexgsss.c +--- openssh-5.8p1/kexgsss.c.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/kexgsss.c 2011-02-14 14:47:02.000000000 +0100 +@@ -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 (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-5.8p1/kex.h.gsskex openssh-5.8p1/kex.h +--- openssh-5.8p1/kex.h.gsskex 2011-02-14 14:47:01.000000000 +0100 ++++ openssh-5.8p1/kex.h 2011-02-14 15:10:05.000000000 +0100 +@@ -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-5.8p1/key.c.gsskex openssh-5.8p1/key.c +--- openssh-5.8p1/key.c.gsskex 2011-02-04 01:48:34.000000000 +0100 ++++ openssh-5.8p1/key.c 2011-02-14 14:47:02.000000000 +0100 +@@ -971,6 +971,8 @@ key_ssh_name_from_type_nid(int type, int + } + break; + #endif /* OPENSSL_HAS_ECC */ ++ case KEY_NULL: ++ return "null"; + } + return "ssh-unknown"; + } +@@ -1276,6 +1278,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-5.8p1/key.h.gsskex openssh-5.8p1/key.h +--- openssh-5.8p1/key.h.gsskex 2010-11-05 00:19:49.000000000 +0100 ++++ openssh-5.8p1/key.h 2011-02-14 14:47:02.000000000 +0100 +@@ -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-5.8p1/Makefile.in.gsskex openssh-5.8p1/Makefile.in +--- openssh-5.8p1/Makefile.in.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/Makefile.in 2011-02-14 15:08:34.000000000 +0100 +@@ -77,6 +77,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 + +@@ -93,7 +94,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-5.8p1/monitor.c.gsskex openssh-5.8p1/monitor.c +--- openssh-5.8p1/monitor.c.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/monitor.c 2011-02-14 14:47:02.000000000 +0100 +@@ -176,6 +176,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 +@@ -256,6 +258,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}, +@@ -268,6 +271,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}, +@@ -384,6 +393,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; + +@@ -470,6 +483,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); +@@ -1755,6 +1772,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); +@@ -1961,6 +1985,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; + +@@ -1988,6 +2015,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); +@@ -2005,6 +2035,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); + } +@@ -2016,6 +2047,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); +@@ -2042,7 +2076,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); +@@ -2055,6 +2093,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-5.8p1/monitor.h.gsskex openssh-5.8p1/monitor.h +--- openssh-5.8p1/monitor.h.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/monitor.h 2011-02-14 14:47:02.000000000 +0100 +@@ -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-5.8p1/monitor_wrap.c.gsskex openssh-5.8p1/monitor_wrap.c +--- openssh-5.8p1/monitor_wrap.c.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/monitor_wrap.c 2011-02-14 14:47:02.000000000 +0100 +@@ -1251,7 +1251,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; +@@ -1268,6 +1268,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-5.8p1/monitor_wrap.h.gsskex openssh-5.8p1/monitor_wrap.h +--- openssh-5.8p1/monitor_wrap.h.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/monitor_wrap.h 2011-02-14 14:47:02.000000000 +0100 +@@ -60,8 +60,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-5.8p1/readconf.c.gsskex openssh-5.8p1/readconf.c +--- openssh-5.8p1/readconf.c.gsskex 2010-11-20 05:19:38.000000000 +0100 ++++ openssh-5.8p1/readconf.c 2011-02-14 14:47:02.000000000 +0100 +@@ -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 }, +@@ -479,10 +490,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; +@@ -1092,7 +1123,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; +@@ -1193,8 +1229,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-5.8p1/readconf.h.gsskex openssh-5.8p1/readconf.h +--- openssh-5.8p1/readconf.h.gsskex 2010-11-20 05:19:38.000000000 +0100 ++++ openssh-5.8p1/readconf.h 2011-02-14 14:47:02.000000000 +0100 +@@ -46,7 +46,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-5.8p1/servconf.c.gsskex openssh-5.8p1/servconf.c +--- openssh-5.8p1/servconf.c.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/servconf.c 2011-02-14 15:11:09.000000000 +0100 +@@ -97,7 +97,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; +@@ -230,8 +233,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) +@@ -330,7 +339,9 @@ typedef enum { + sBanner, sShowPatchLevel, sUseDNS, sHostbasedAuthentication, + sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, + sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, +- sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, ++ sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, ++ sGssKeyEx, sGssStoreRekey, ++ sAcceptEnv, sPermitTunnel, + sMatch, sPermitOpen, sForceCommand, sChrootDirectory, + sUsePrivilegeSeparation, sAllowAgentForwarding, + sZeroKnowledgePasswordAuthentication, sHostCertificate, +@@ -397,10 +408,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 }, +@@ -963,10 +984,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; +@@ -1748,7 +1781,10 @@ dump_config(ServerOptions *o) + #endif + #ifdef GSSAPI + dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); ++ dump_cfg_fmtint(sGssKeyEx, o->gss_keyex); + dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); ++ 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-5.8p1/servconf.h.gsskex openssh-5.8p1/servconf.h +--- openssh-5.8p1/servconf.h.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/servconf.h 2011-02-14 14:47:02.000000000 +0100 +@@ -97,7 +97,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-5.8p1/ssh_config.5.gsskex openssh-5.8p1/ssh_config.5 +--- openssh-5.8p1/ssh_config.5.gsskex 2010-12-26 04:26:48.000000000 +0100 ++++ openssh-5.8p1/ssh_config.5 2011-02-14 14:47:02.000000000 +0100 +@@ -508,11 +508,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-5.8p1/ssh_config.gsskex openssh-5.8p1/ssh_config +--- openssh-5.8p1/ssh_config.gsskex 2011-02-14 14:47:01.000000000 +0100 ++++ openssh-5.8p1/ssh_config 2011-02-14 14:47:02.000000000 +0100 +@@ -26,6 +26,8 @@ + # HostbasedAuthentication no + # GSSAPIAuthentication no + # GSSAPIDelegateCredentials no ++# GSSAPIKeyExchange no ++# GSSAPITrustDNS no + # BatchMode no + # CheckHostIP yes + # AddressFamily any +diff -up openssh-5.8p1/sshconnect2.c.gsskex openssh-5.8p1/sshconnect2.c +--- openssh-5.8p1/sshconnect2.c.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/sshconnect2.c 2011-02-14 14:47:02.000000000 +0100 +@@ -161,9 +161,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; +@@ -206,6 +231,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); + +@@ -216,10 +252,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); +@@ -314,6 +370,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 *); +@@ -329,6 +386,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, +@@ -635,19 +697,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++; +@@ -744,8 +818,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"); +@@ -855,6 +929,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-5.8p1/sshd.c.gsskex openssh-5.8p1/sshd.c +--- openssh-5.8p1/sshd.c.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/sshd.c 2011-02-14 15:11:56.000000000 +0100 +@@ -123,6 +123,10 @@ + #include "audit.h" + #include "version.h" + ++#ifdef USE_SECURITY_SESSION_API ++#include ++#endif ++ + #ifdef LIBWRAP + #include + #include +@@ -1609,10 +1613,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); +@@ -1945,6 +1952,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 +@@ -2347,6 +2408,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; +@@ -2354,6 +2457,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-5.8p1/sshd_config.5.gsskex openssh-5.8p1/sshd_config.5 +--- openssh-5.8p1/sshd_config.5.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/sshd_config.5 2011-02-14 14:47:02.000000000 +0100 +@@ -423,12 +423,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-5.8p1/sshd_config.gsskex openssh-5.8p1/sshd_config +--- openssh-5.8p1/sshd_config.gsskex 2011-02-14 14:47:02.000000000 +0100 ++++ openssh-5.8p1/sshd_config 2011-02-14 15:12:38.000000000 +0100 +@@ -80,6 +80,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-5.8p1/ssh-gss.h.gsskex openssh-5.8p1/ssh-gss.h +--- openssh-5.8p1/ssh-gss.h.gsskex 2007-06-12 15:40:39.000000000 +0200 ++++ openssh-5.8p1/ssh-gss.h 2011-02-14 14:47:02.000000000 +0100 +@@ -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-5.8p1-kuserok.patch b/openssh-5.8p1-kuserok.patch new file mode 100644 index 0000000..fcd05d7 --- /dev/null +++ b/openssh-5.8p1-kuserok.patch @@ -0,0 +1,167 @@ +diff -up openssh-5.8p1/auth-krb5.c.kuserok openssh-5.8p1/auth-krb5.c +--- openssh-5.8p1/auth-krb5.c.kuserok 2009-12-21 00:49:22.000000000 +0100 ++++ openssh-5.8p1/auth-krb5.c 2011-02-14 09:15:12.000000000 +0100 +@@ -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.8p1/gss-serv-krb5.c.kuserok openssh-5.8p1/gss-serv-krb5.c +--- openssh-5.8p1/gss-serv-krb5.c.kuserok 2006-09-01 07:38:36.000000000 +0200 ++++ openssh-5.8p1/gss-serv-krb5.c 2011-02-14 09:15:12.000000000 +0100 +@@ -57,6 +57,7 @@ extern ServerOptions options; + #endif + + 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 */ + +@@ -97,7 +98,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client + krb5_get_err_text(krb_context, retval)); + return 0; + } +- if (krb5_kuserok(krb_context, princ, name)) { ++ if (ssh_krb5_kuserok(krb_context, princ, name)) { + retval = 1; + logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", + name, (char *)client->displayname.value); +diff -up openssh-5.8p1/servconf.c.kuserok openssh-5.8p1/servconf.c +--- openssh-5.8p1/servconf.c.kuserok 2011-02-14 09:15:12.000000000 +0100 ++++ openssh-5.8p1/servconf.c 2011-02-14 09:20:22.000000000 +0100 +@@ -142,6 +142,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 + if (use_privsep == -1) + use_privsep = 1; + ++ if (options->use_kuserok == -1) ++ options->use_kuserok = 1; + #ifndef HAVE_MMAP + if (use_privsep && options->compression == 1) { + error("This platform does not support both privilege " +@@ -312,7 +315,7 @@ typedef enum { + sPermitRootLogin, sLogFacility, sLogLevel, + sRhostsRSAAuthentication, sRSAAuthentication, + sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, +- sKerberosGetAFSToken, ++ sKerberosGetAFSToken, sKerberosUseKuserok, + sKerberosTgtPassing, sChallengeResponseAuthentication, + sPasswordAuthentication, sKbdInteractiveAuthentication, + sListenAddress, sAddressFamily, +@@ -381,11 +384,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 }, +@@ -1341,6 +1346,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') +@@ -1544,6 +1553,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); + + M_CP_STROPT(banner); + if (preauth) +@@ -1764,6 +1774,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.8p1/servconf.h.kuserok openssh-5.8p1/servconf.h +--- openssh-5.8p1/servconf.h.kuserok 2011-02-14 09:15:12.000000000 +0100 ++++ openssh-5.8p1/servconf.h 2011-02-14 09:15:12.000000000 +0100 +@@ -157,6 +157,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.8p1/sshd_config.5.kuserok openssh-5.8p1/sshd_config.5 +--- openssh-5.8p1/sshd_config.5.kuserok 2011-02-14 09:15:12.000000000 +0100 ++++ openssh-5.8p1/sshd_config.5 2011-02-14 09:17:11.000000000 +0100 +@@ -574,6 +574,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. +@@ -715,6 +719,7 @@ Available keywords are + .Cm HostbasedUsesNameFromPacketOnly , + .Cm KbdInteractiveAuthentication , + .Cm KerberosAuthentication , ++.Cm KerberosUseKuserok , + .Cm MaxAuthTries , + .Cm MaxSessions , + .Cm PubkeyAuthentication , +diff -up openssh-5.8p1/sshd_config.kuserok openssh-5.8p1/sshd_config +--- openssh-5.8p1/sshd_config.kuserok 2011-02-14 09:15:12.000000000 +0100 ++++ openssh-5.8p1/sshd_config 2011-02-14 09:15:12.000000000 +0100 +@@ -73,6 +73,7 @@ ChallengeResponseAuthentication no + #KerberosOrLocalPasswd yes + #KerberosTicketCleanup yes + #KerberosGetAFSToken no ++#KerberosUseKuserok yes + + # GSSAPI options + #GSSAPIAuthentication no diff --git a/openssh-5.8p1-mls.patch b/openssh-5.8p1-mls.patch new file mode 100644 index 0000000..525e6b5 --- /dev/null +++ b/openssh-5.8p1-mls.patch @@ -0,0 +1,400 @@ +diff -up openssh-5.8p1/misc.c.mls openssh-5.8p1/misc.c +--- openssh-5.8p1/misc.c.mls 2011-01-13 02:21:36.000000000 +0100 ++++ openssh-5.8p1/misc.c 2011-02-12 15:05:06.000000000 +0100 +@@ -427,6 +427,7 @@ char * + colon(char *cp) + { + int flag = 0; ++ int start = 1; + + if (*cp == ':') /* Leading colon is part of file name. */ + return NULL; +@@ -442,6 +443,13 @@ colon(char *cp) + return (cp); + if (*cp == '/') + return NULL; ++ if (start) { ++ /* Slash on beginning or after dots only denotes file name. */ ++ if (*cp == '/') ++ return (0); ++ if (*cp != '.') ++ start = 0; ++ } + } + return NULL; + } +diff -up openssh-5.8p1/openbsd-compat/port-linux.c.mls openssh-5.8p1/openbsd-compat/port-linux.c +--- openssh-5.8p1/openbsd-compat/port-linux.c.mls 2011-02-12 15:05:06.000000000 +0100 ++++ openssh-5.8p1/openbsd-compat/port-linux.c 2011-02-12 15:09:23.000000000 +0100 +@@ -40,13 +40,164 @@ + #ifdef WITH_SELINUX + #include + #include ++#include + #include ++#include ++#include ++ ++#ifdef HAVE_LINUX_AUDIT ++#include ++#include ++#endif + + extern ServerOptions options; + extern Authctxt *the_authctxt; + extern int inetd_flag; + extern int rexeced_flag; + ++/* Send audit message */ ++static int ++send_audit_message(int success, security_context_t default_context, ++ security_context_t selected_context) ++{ ++ int rc=0; ++#ifdef HAVE_LINUX_AUDIT ++ char *msg = NULL; ++ int audit_fd = audit_open(); ++ security_context_t default_raw=NULL; ++ security_context_t selected_raw=NULL; ++ rc = -1; ++ if (audit_fd < 0) { ++ if (errno == EINVAL || errno == EPROTONOSUPPORT || ++ errno == EAFNOSUPPORT) ++ return 0; /* No audit support in kernel */ ++ error("Error connecting to audit system."); ++ return rc; ++ } ++ if (selinux_trans_to_raw_context(default_context, &default_raw) < 0) { ++ error("Error translating default context."); ++ default_raw = NULL; ++ } ++ if (selinux_trans_to_raw_context(selected_context, &selected_raw) < 0) { ++ error("Error translating selected context."); ++ selected_raw = NULL; ++ } ++ if (asprintf(&msg, "sshd: default-context=%s selected-context=%s", ++ default_raw ? default_raw : (default_context ? default_context: "?"), ++ selected_context ? selected_raw : (selected_context ? selected_context :"?")) < 0) { ++ error("Error allocating memory."); ++ goto out; ++ } ++ if (audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE, ++ msg, NULL, NULL, NULL, success) <= 0) { ++ error("Error sending audit message."); ++ goto out; ++ } ++ rc = 0; ++ out: ++ free(msg); ++ freecon(default_raw); ++ freecon(selected_raw); ++ close(audit_fd); ++#endif ++ return rc; ++} ++ ++static int ++mls_range_allowed(security_context_t src, security_context_t dst) ++{ ++ struct av_decision avd; ++ int retval; ++ unsigned int bit = CONTEXT__CONTAINS; ++ ++ debug("%s: src:%s dst:%s", __func__, src, dst); ++ retval = security_compute_av(src, dst, SECCLASS_CONTEXT, bit, &avd); ++ if (retval || ((bit & avd.allowed) != bit)) ++ return 0; ++ ++ return 1; ++} ++ ++static int ++get_user_context(const char *sename, const char *role, const char *lvl, ++ security_context_t *sc) { ++#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL ++ if (lvl == NULL || lvl[0] == '\0' || get_default_context_with_level(sename, lvl, NULL, sc) != 0) { ++ /* User may have requested a level completely outside of his ++ allowed range. We get a context just for auditing as the ++ range check below will certainly fail for default context. */ ++#endif ++ if (get_default_context(sename, NULL, sc) != 0) { ++ *sc = NULL; ++ return -1; ++ } ++#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL ++ } ++#endif ++ if (role != NULL && role[0]) { ++ context_t con; ++ char *type=NULL; ++ if (get_default_type(role, &type) != 0) { ++ error("get_default_type: failed to get default type for '%s'", ++ role); ++ goto out; ++ } ++ con = context_new(*sc); ++ if (!con) { ++ goto out; ++ } ++ context_role_set(con, role); ++ context_type_set(con, type); ++ freecon(*sc); ++ *sc = strdup(context_str(con)); ++ context_free(con); ++ if (!*sc) ++ return -1; ++ } ++#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL ++ if (lvl != NULL && lvl[0]) { ++ /* verify that the requested range is obtained */ ++ context_t con; ++ security_context_t obtained_raw; ++ security_context_t requested_raw; ++ con = context_new(*sc); ++ if (!con) { ++ goto out; ++ } ++ context_range_set(con, lvl); ++ if (selinux_trans_to_raw_context(*sc, &obtained_raw) < 0) { ++ context_free(con); ++ goto out; ++ } ++ if (selinux_trans_to_raw_context(context_str(con), &requested_raw) < 0) { ++ freecon(obtained_raw); ++ context_free(con); ++ goto out; ++ } ++ ++ debug("get_user_context: obtained context '%s' requested context '%s'", ++ obtained_raw, requested_raw); ++ if (strcmp(obtained_raw, requested_raw)) { ++ /* set the context to the real requested one but fail */ ++ freecon(requested_raw); ++ freecon(obtained_raw); ++ freecon(*sc); ++ *sc = strdup(context_str(con)); ++ context_free(con); ++ return -1; ++ } ++ freecon(requested_raw); ++ freecon(obtained_raw); ++ context_free(con); ++ } ++#endif ++ return 0; ++ out: ++ freecon(*sc); ++ *sc = NULL; ++ return -1; ++} ++ + static void + ssh_selinux_get_role_level(char **role, const char **level) + { +@@ -65,14 +216,16 @@ ssh_selinux_get_role_level(char **role, + } + + /* Return the default security context for the given username */ +-static security_context_t +-ssh_selinux_getctxbyname(char *pwname) ++static int ++ssh_selinux_getctxbyname(char *pwname, ++ security_context_t *default_sc, security_context_t *user_sc) + { + security_context_t sc = NULL; + char *sename, *lvl; + char *role; + const char *reqlvl; + int r = 0; ++ context_t con; + + ssh_selinux_get_role_level(&role, &reqlvl); + #ifdef HAVE_GETSEUSERBYNAME +@@ -82,38 +235,63 @@ ssh_selinux_getctxbyname(char *pwname) + } + #else + sename = pwname; +- lvl = NULL; ++ lvl = ""; + #endif + + if (r == 0) { + #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL +- if (role != NULL && role[0]) +- r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc); +- else +- r = get_default_context_with_level(sename, lvl, NULL, &sc); ++ r = get_default_context_with_level(sename, lvl, NULL, default_sc); + #else +- if (role != NULL && role[0]) +- r = get_default_context_with_role(sename, role, NULL, &sc); +- else +- r = get_default_context(sename, NULL, &sc); ++ r = get_default_context(sename, NULL, default_sc); + #endif + } + +- if (r != 0) { +- switch (security_getenforce()) { +- case -1: +- fatal("%s: ssh_selinux_getctxbyname: " +- "security_getenforce() failed", __func__); +- case 0: +- error("%s: Failed to get default SELinux security " +- "context for %s", __func__, pwname); +- break; +- default: +- fatal("%s: Failed to get default SELinux security " +- "context for %s (in enforcing mode)", +- __func__, pwname); ++ if (r == 0) { ++ /* If launched from xinetd, we must use current level */ ++ if (inetd_flag && !rexeced_flag) { ++ security_context_t sshdsc=NULL; ++ ++ if (getcon_raw(&sshdsc) < 0) ++ fatal("failed to allocate security context"); ++ ++ if ((con=context_new(sshdsc)) == NULL) ++ fatal("failed to allocate selinux context"); ++ reqlvl = context_range_get(con); ++ freecon(sshdsc); ++ if (reqlvl !=NULL && lvl != NULL && strcmp(reqlvl, lvl) == 0) ++ /* we actually don't change level */ ++ reqlvl = ""; ++ ++ debug("%s: current connection level '%s'", __func__, reqlvl); ++ } ++ ++ if ((reqlvl != NULL && reqlvl[0]) || (role != NULL && role[0])) { ++ r = get_user_context(sename, role, reqlvl, user_sc); ++ ++ if (r == 0 && reqlvl != NULL && reqlvl[0]) { ++ security_context_t default_level_sc = *default_sc; ++ if (role != NULL && role[0]) { ++ if (get_user_context(sename, role, lvl, &default_level_sc) < 0) ++ default_level_sc = *default_sc; ++ } ++ /* verify that the requested range is contained in the user range */ ++ if (mls_range_allowed(default_level_sc, *user_sc)) { ++ logit("permit MLS level %s (user range %s)", reqlvl, lvl); ++ } else { ++ r = -1; ++ error("deny MLS level %s (user range %s)", reqlvl, lvl); ++ } ++ if (default_level_sc != *default_sc) ++ freecon(default_level_sc); ++ } ++ } else { ++ *user_sc = *default_sc; + } + } ++ if (r != 0) { ++ error("%s: Failed to get default SELinux security " ++ "context for %s", __func__, pwname); ++ } + + #ifdef HAVE_GETSEUSERBYNAME + if (sename != NULL) +@@ -121,8 +299,12 @@ ssh_selinux_getctxbyname(char *pwname) + if (lvl != NULL) + xfree(lvl); + #endif +- +- return (sc); ++ if (role != NULL) ++ xfree(role); ++ if (con) ++ context_free(con); ++ ++ return (r); + } + + /* Setup environment variables for pam_selinux */ +@@ -160,6 +342,8 @@ void + ssh_selinux_setup_exec_context(char *pwname) + { + security_context_t user_ctx = NULL; ++ int r = 0; ++ security_context_t default_ctx = NULL; + + if (!ssh_selinux_enabled()) + return; +@@ -184,22 +368,45 @@ ssh_selinux_setup_exec_context(char *pwn + + debug3("%s: setting execution context", __func__); + +- user_ctx = ssh_selinux_getctxbyname(pwname); +- if (setexeccon(user_ctx) != 0) { ++ r = ssh_selinux_getctxbyname(pwname, &default_ctx, &user_ctx); ++ if (r >= 0) { ++ r = setexeccon(user_ctx); ++ if (r < 0) { ++ error("%s: Failed to set SELinux execution context %s for %s", ++ __func__, user_ctx, pwname); ++ } ++#ifdef HAVE_SETKEYCREATECON ++ else if (setkeycreatecon(user_ctx) < 0) { ++ error("%s: Failed to set SELinux keyring creation context %s for %s", ++ __func__, user_ctx, pwname); ++ } ++#endif ++ } ++ if (user_ctx == NULL) { ++ user_ctx = default_ctx; ++ } ++ if (r < 0 || user_ctx != default_ctx) { ++ /* audit just the case when user changed a role or there was ++ a failure */ ++ send_audit_message(r >= 0, default_ctx, user_ctx); ++ } ++ if (r < 0) { + switch (security_getenforce()) { + case -1: + fatal("%s: security_getenforce() failed", __func__); + case 0: +- error("%s: Failed to set SELinux execution " +- "context for %s", __func__, pwname); ++ error("%s: SELinux failure. Continuing in permissive mode.", ++ __func__); + break; + default: +- fatal("%s: Failed to set SELinux execution context " +- "for %s (in enforcing mode)", __func__, pwname); ++ fatal("%s: SELinux failure. Aborting connection.", ++ __func__); + } + } +- if (user_ctx != NULL) ++ if (user_ctx != NULL && user_ctx != default_ctx) + freecon(user_ctx); ++ if (default_ctx != NULL) ++ freecon(default_ctx); + + debug3("%s: done", __func__); + } +@@ -217,7 +424,10 @@ ssh_selinux_setup_pty(char *pwname, cons + + debug3("%s: setting TTY context on %s", __func__, tty); + +- user_ctx = ssh_selinux_getctxbyname(pwname); ++ if (getexeccon(&user_ctx) < 0) { ++ error("%s: getexeccon: %s", __func__, strerror(errno)); ++ goto out; ++ } + + /* XXX: should these calls fatal() upon failure in enforcing mode? */ + +diff -up openssh-5.8p1/sshd.c.mls openssh-5.8p1/sshd.c +--- openssh-5.8p1/sshd.c.mls 2011-02-12 15:05:05.000000000 +0100 ++++ openssh-5.8p1/sshd.c 2011-02-12 15:05:06.000000000 +0100 +@@ -2011,6 +2011,9 @@ main(int ac, char **av) + restore_uid(); + } + #endif ++#ifdef WITH_SELINUX ++ ssh_selinux_setup_exec_context(authctxt->pw->pw_name); ++#endif + #ifdef USE_PAM + if (options.use_pam) { + do_pam_setcred(1); diff --git a/openssh-5.8p1-pam_selinux.patch b/openssh-5.8p1-pam_selinux.patch new file mode 100644 index 0000000..c8cceea --- /dev/null +++ b/openssh-5.8p1-pam_selinux.patch @@ -0,0 +1,156 @@ +diff -up openssh-5.8p1/auth-pam.c.pam_selinux openssh-5.8p1/auth-pam.c +--- openssh-5.8p1/auth-pam.c.pam_selinux 2009-07-12 14:07:21.000000000 +0200 ++++ openssh-5.8p1/auth-pam.c 2011-02-12 10:49:57.000000000 +0100 +@@ -1069,7 +1069,7 @@ is_pam_session_open(void) + * during the ssh authentication process. + */ + int +-do_pam_putenv(char *name, char *value) ++do_pam_putenv(char *name, const char *value) + { + int ret = 1; + #ifdef HAVE_PAM_PUTENV +diff -up openssh-5.8p1/auth-pam.h.pam_selinux openssh-5.8p1/auth-pam.h +--- openssh-5.8p1/auth-pam.h.pam_selinux 2004-09-11 14:17:26.000000000 +0200 ++++ openssh-5.8p1/auth-pam.h 2011-02-12 10:49:57.000000000 +0100 +@@ -38,7 +38,7 @@ void do_pam_session(void); + void do_pam_set_tty(const char *); + void do_pam_setcred(int ); + void do_pam_chauthtok(void); +-int do_pam_putenv(char *, char *); ++int do_pam_putenv(char *, const char *); + char ** fetch_pam_environment(void); + char ** fetch_pam_child_environment(void); + void free_pam_environment(char **); +diff -up openssh-5.8p1/openbsd-compat/port-linux.c.pam_selinux openssh-5.8p1/openbsd-compat/port-linux.c +--- openssh-5.8p1/openbsd-compat/port-linux.c.pam_selinux 2011-02-12 10:49:57.000000000 +0100 ++++ openssh-5.8p1/openbsd-compat/port-linux.c 2011-02-12 10:55:52.000000000 +0100 +@@ -36,6 +36,7 @@ + #include "hostfile.h" + #include "auth.h" + #include "xmalloc.h" ++#include "servconf.h" + + #ifdef WITH_SELINUX + #include +@@ -50,6 +51,7 @@ + #include + #endif + ++extern ServerOptions options; + extern Authctxt *the_authctxt; + extern int inetd_flag; + extern int rexeced_flag; +@@ -197,29 +199,38 @@ get_user_context(const char *sename, con + return -1; + } + ++static void ++ssh_selinux_get_role_level(char **role, const char **level) ++{ ++ *role = NULL; ++ *level = NULL; ++ if (the_authctxt) { ++ if (the_authctxt->role != NULL) { ++ char *slash; ++ *role = xstrdup(the_authctxt->role); ++ if ((slash = strchr(*role, '/')) != NULL) { ++ *slash = '\0'; ++ *level = slash + 1; ++ } ++ } ++ } ++} ++ + /* Return the default security context for the given username */ + static int + ssh_selinux_getctxbyname(char *pwname, + security_context_t *default_sc, security_context_t *user_sc) + { + char *sename, *lvl; +- const char *reqlvl = NULL; +- char *role = NULL; ++ const char *reqlvl; ++ char *role; + int r = -1; + context_t con = NULL; + + *default_sc = NULL; + *user_sc = NULL; +- if (the_authctxt) { +- if (the_authctxt->role != NULL) { +- char *slash; +- role = xstrdup(the_authctxt->role); +- if ((slash = strchr(role, '/')) != NULL) { +- *slash = '\0'; +- reqlvl = slash + 1; +- } +- } +- } ++ ++ ssh_selinux_get_role_level(&role, &reqlvl); + + #ifdef HAVE_GETSEUSERBYNAME + if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) { +@@ -300,6 +311,36 @@ ssh_selinux_getctxbyname(char *pwname, + return (r); + } + ++/* Setup environment variables for pam_selinux */ ++static int ++ssh_selinux_setup_pam_variables(void) ++{ ++ const char *reqlvl; ++ char *role; ++ char *use_current; ++ int rv; ++ ++ debug3("%s: setting execution context", __func__); ++ ++ ssh_selinux_get_role_level(&role, &reqlvl); ++ ++ rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : ""); ++ ++ if (inetd_flag && !rexeced_flag) { ++ use_current = "1"; ++ } else { ++ use_current = ""; ++ rv = rv || do_pam_putenv("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: ""); ++ } ++ ++ rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current); ++ ++ if (role != NULL) ++ xfree(role); ++ ++ return rv; ++} ++ + /* Set the execution context to the default for the specified user */ + void + ssh_selinux_setup_exec_context(char *pwname) +@@ -311,6 +352,24 @@ ssh_selinux_setup_exec_context(char *pwn + if (!ssh_selinux_enabled()) + return; + ++ if (options.use_pam) { ++ /* do not compute context, just setup environment for pam_selinux */ ++ if (ssh_selinux_setup_pam_variables()) { ++ switch (security_getenforce()) { ++ case -1: ++ fatal("%s: security_getenforce() failed", __func__); ++ case 0: ++ error("%s: SELinux PAM variable setup failure. Continuing in permissive mode.", ++ __func__); ++ break; ++ default: ++ fatal("%s: SELinux PAM variable setup failure. Aborting connection.", ++ __func__); ++ } ++ } ++ return; ++ } ++ + debug3("%s: setting execution context", __func__); + + r = ssh_selinux_getctxbyname(pwname, &default_ctx, &user_ctx); diff --git a/openssh-5.8p1-randclean.patch b/openssh-5.8p1-randclean.patch new file mode 100644 index 0000000..378f367 --- /dev/null +++ b/openssh-5.8p1-randclean.patch @@ -0,0 +1,13 @@ +diff -up openssh-5.8p1/entropy.c.randclean openssh-5.8p1/entropy.c +--- openssh-5.8p1/entropy.c.randclean 2011-01-13 11:05:29.000000000 +0100 ++++ openssh-5.8p1/entropy.c 2011-02-14 00:26:31.000000000 +0100 +@@ -159,6 +159,9 @@ init_rng(void) + fatal("OpenSSL version mismatch. Built against %lx, you " + "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay()); + ++ /* clean the PRNG status when exiting the program */ ++ atexit(RAND_cleanup); ++ + #ifndef OPENSSL_PRNG_ONLY + original_uid = getuid(); + original_euid = geteuid(); diff --git a/openssh-5.8p1-selinux-role.patch b/openssh-5.8p1-selinux-role.patch new file mode 100644 index 0000000..f29ad9a --- /dev/null +++ b/openssh-5.8p1-selinux-role.patch @@ -0,0 +1,611 @@ +diff -up openssh-5.8p1/auth1.c.role openssh-5.8p1/auth1.c +--- openssh-5.8p1/auth1.c.role 2010-08-31 14:36:39.000000000 +0200 ++++ openssh-5.8p1/auth1.c 2011-02-12 14:34:11.000000000 +0100 +@@ -384,6 +384,9 @@ do_authentication(Authctxt *authctxt) + { + u_int ulen; + char *user, *style = NULL; ++#ifdef WITH_SELINUX ++ char *role=NULL; ++#endif + + /* Get the name of the user that we wish to log in as. */ + packet_read_expect(SSH_CMSG_USER); +@@ -392,11 +395,24 @@ do_authentication(Authctxt *authctxt) + user = packet_get_cstring(&ulen); + packet_check_eom(); + ++#ifdef WITH_SELINUX ++ if ((role = strchr(user, '/')) != NULL) ++ *role++ = '\0'; ++#endif ++ + if ((style = strchr(user, ':')) != NULL) + *style++ = '\0'; ++#ifdef WITH_SELINUX ++ else ++ if (role && (style = strchr(role, ':')) != NULL) ++ *style++ = '\0'; ++#endif + + authctxt->user = user; + authctxt->style = style; ++#ifdef WITH_SELINUX ++ authctxt->role = role; ++#endif + + /* Verify that the user is a valid user. */ + if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) +diff -up openssh-5.8p1/auth2.c.role openssh-5.8p1/auth2.c +--- openssh-5.8p1/auth2.c.role 2010-08-31 14:36:39.000000000 +0200 ++++ openssh-5.8p1/auth2.c 2011-02-12 14:34:11.000000000 +0100 +@@ -216,6 +216,9 @@ input_userauth_request(int type, u_int32 + Authctxt *authctxt = ctxt; + Authmethod *m = NULL; + char *user, *service, *method, *style = NULL; ++#ifdef WITH_SELINUX ++ char *role = NULL; ++#endif + int authenticated = 0; + + if (authctxt == NULL) +@@ -227,6 +230,11 @@ input_userauth_request(int type, u_int32 + debug("userauth-request for user %s service %s method %s", user, service, method); + debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); + ++#ifdef WITH_SELINUX ++ if ((role = strchr(user, '/')) != NULL) ++ *role++ = 0; ++#endif ++ + if ((style = strchr(user, ':')) != NULL) + *style++ = 0; + +@@ -252,8 +260,15 @@ input_userauth_request(int type, u_int32 + use_privsep ? " [net]" : ""); + authctxt->service = xstrdup(service); + authctxt->style = style ? xstrdup(style) : NULL; +- if (use_privsep) ++#ifdef WITH_SELINUX ++ authctxt->role = role ? xstrdup(role) : NULL; ++#endif ++ if (use_privsep) { + mm_inform_authserv(service, style); ++#ifdef WITH_SELINUX ++ mm_inform_authrole(role); ++#endif ++ } + userauth_banner(); + } else if (strcmp(user, authctxt->user) != 0 || + strcmp(service, authctxt->service) != 0) { +diff -up openssh-5.8p1/auth2-gss.c.role openssh-5.8p1/auth2-gss.c +--- openssh-5.8p1/auth2-gss.c.role 2007-12-02 12:59:45.000000000 +0100 ++++ openssh-5.8p1/auth2-gss.c 2011-02-12 14:34:11.000000000 +0100 +@@ -258,6 +258,7 @@ input_gssapi_mic(int type, u_int32_t ple + Authctxt *authctxt = ctxt; + Gssctxt *gssctxt; + int authenticated = 0; ++ char *micuser; + Buffer b; + gss_buffer_desc mic, gssbuf; + u_int len; +@@ -270,7 +271,13 @@ input_gssapi_mic(int type, u_int32_t ple + mic.value = packet_get_string(&len); + mic.length = len; + +- ssh_gssapi_buildmic(&b, authctxt->user, authctxt->service, ++#ifdef WITH_SELINUX ++ if (authctxt->role && (strlen(authctxt->role) > 0)) ++ xasprintf(&micuser, "%s/%s", authctxt->user, authctxt->role); ++ else ++#endif ++ micuser = authctxt->user; ++ ssh_gssapi_buildmic(&b, micuser, authctxt->service, + "gssapi-with-mic"); + + gssbuf.value = buffer_ptr(&b); +@@ -282,6 +289,8 @@ input_gssapi_mic(int type, u_int32_t ple + logit("GSSAPI MIC check failed"); + + buffer_free(&b); ++ if (micuser != authctxt->user) ++ xfree(micuser); + xfree(mic.value); + + authctxt->postponed = 0; +diff -up openssh-5.8p1/auth2-hostbased.c.role openssh-5.8p1/auth2-hostbased.c +--- openssh-5.8p1/auth2-hostbased.c.role 2011-02-12 14:34:10.000000000 +0100 ++++ openssh-5.8p1/auth2-hostbased.c 2011-02-12 14:34:11.000000000 +0100 +@@ -106,7 +106,15 @@ userauth_hostbased(Authctxt *authctxt) + buffer_put_string(&b, session_id2, session_id2_len); + /* reconstruct packet */ + buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); +- buffer_put_cstring(&b, authctxt->user); ++#ifdef WITH_SELINUX ++ if (authctxt->role) { ++ buffer_put_int(&b, strlen(authctxt->user)+strlen(authctxt->role)+1); ++ buffer_append(&b, authctxt->user, strlen(authctxt->user)); ++ buffer_put_char(&b, '/'); ++ buffer_append(&b, authctxt->role, strlen(authctxt->role)); ++ } else ++#endif ++ buffer_put_cstring(&b, authctxt->user); + buffer_put_cstring(&b, service); + buffer_put_cstring(&b, "hostbased"); + buffer_put_string(&b, pkalg, alen); +diff -up openssh-5.8p1/auth2-pubkey.c.role openssh-5.8p1/auth2-pubkey.c +--- openssh-5.8p1/auth2-pubkey.c.role 2011-02-12 14:34:11.000000000 +0100 ++++ openssh-5.8p1/auth2-pubkey.c 2011-02-12 14:34:11.000000000 +0100 +@@ -122,7 +122,15 @@ userauth_pubkey(Authctxt *authctxt) + } + /* reconstruct packet */ + buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); +- buffer_put_cstring(&b, authctxt->user); ++#ifdef WITH_SELINUX ++ if (authctxt->role) { ++ buffer_put_int(&b, strlen(authctxt->user)+strlen(authctxt->role)+1); ++ buffer_append(&b, authctxt->user, strlen(authctxt->user)); ++ buffer_put_char(&b, '/'); ++ buffer_append(&b, authctxt->role, strlen(authctxt->role)); ++ } else ++#endif ++ buffer_put_cstring(&b, authctxt->user); + buffer_put_cstring(&b, + datafellows & SSH_BUG_PKSERVICE ? + "ssh-userauth" : +diff -up openssh-5.8p1/auth.h.role openssh-5.8p1/auth.h +--- openssh-5.8p1/auth.h.role 2011-02-12 14:34:10.000000000 +0100 ++++ openssh-5.8p1/auth.h 2011-02-12 14:34:11.000000000 +0100 +@@ -58,6 +58,9 @@ struct Authctxt { + char *service; + struct passwd *pw; /* set if 'valid' */ + char *style; ++#ifdef WITH_SELINUX ++ char *role; ++#endif + void *kbdintctxt; + void *jpake_ctx; + #ifdef BSD_AUTH +diff -up openssh-5.8p1/auth-pam.c.role openssh-5.8p1/auth-pam.c +--- openssh-5.8p1/auth-pam.c.role 2009-07-12 14:07:21.000000000 +0200 ++++ openssh-5.8p1/auth-pam.c 2011-02-12 14:34:11.000000000 +0100 +@@ -1069,7 +1069,7 @@ is_pam_session_open(void) + * during the ssh authentication process. + */ + int +-do_pam_putenv(char *name, char *value) ++do_pam_putenv(char *name, const char *value) + { + int ret = 1; + #ifdef HAVE_PAM_PUTENV +diff -up openssh-5.8p1/auth-pam.h.role openssh-5.8p1/auth-pam.h +--- openssh-5.8p1/auth-pam.h.role 2004-09-11 14:17:26.000000000 +0200 ++++ openssh-5.8p1/auth-pam.h 2011-02-12 14:34:11.000000000 +0100 +@@ -38,7 +38,7 @@ void do_pam_session(void); + void do_pam_set_tty(const char *); + void do_pam_setcred(int ); + void do_pam_chauthtok(void); +-int do_pam_putenv(char *, char *); ++int do_pam_putenv(char *, const char *); + char ** fetch_pam_environment(void); + char ** fetch_pam_child_environment(void); + void free_pam_environment(char **); +diff -up openssh-5.8p1/monitor.c.role openssh-5.8p1/monitor.c +--- openssh-5.8p1/monitor.c.role 2011-02-12 14:34:11.000000000 +0100 ++++ openssh-5.8p1/monitor.c 2011-02-12 14:34:11.000000000 +0100 +@@ -138,6 +138,9 @@ int mm_answer_sign(int, Buffer *); + int mm_answer_pwnamallow(int, Buffer *); + int mm_answer_auth2_read_banner(int, Buffer *); + int mm_answer_authserv(int, Buffer *); ++#ifdef WITH_SELINUX ++int mm_answer_authrole(int, Buffer *); ++#endif + int mm_answer_authpassword(int, Buffer *); + int mm_answer_bsdauthquery(int, Buffer *); + int mm_answer_bsdauthrespond(int, Buffer *); +@@ -218,6 +221,9 @@ struct mon_table mon_dispatch_proto20[] + {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, + {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, + {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, ++#ifdef WITH_SELINUX ++ {MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole}, ++#endif + {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, + {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, + #ifdef USE_PAM +@@ -703,6 +709,9 @@ mm_answer_pwnamallow(int sock, Buffer *m + else { + /* Allow service/style information on the auth context */ + monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); ++#ifdef WITH_SELINUX ++ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHROLE, 1); ++#endif + monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); + } + +@@ -747,6 +756,25 @@ mm_answer_authserv(int sock, Buffer *m) + return (0); + } + ++#ifdef WITH_SELINUX ++int ++mm_answer_authrole(int sock, Buffer *m) ++{ ++ monitor_permit_authentications(1); ++ ++ authctxt->role = buffer_get_string(m, NULL); ++ debug3("%s: role=%s", ++ __func__, authctxt->role); ++ ++ if (strlen(authctxt->role) == 0) { ++ xfree(authctxt->role); ++ authctxt->role = NULL; ++ } ++ ++ return (0); ++} ++#endif ++ + int + mm_answer_authpassword(int sock, Buffer *m) + { +@@ -1112,7 +1140,7 @@ static int + monitor_valid_userblob(u_char *data, u_int datalen) + { + Buffer b; +- char *p; ++ char *p, *r; + u_int len; + int fail = 0; + +@@ -1138,6 +1166,8 @@ monitor_valid_userblob(u_char *data, u_i + if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) + fail++; + p = buffer_get_string(&b, NULL); ++ if ((r = strchr(p, '/')) != NULL) ++ *r = '\0'; + if (strcmp(authctxt->user, p) != 0) { + logit("wrong user name passed to monitor: expected %s != %.100s", + authctxt->user, p); +@@ -1169,7 +1199,7 @@ monitor_valid_hostbasedblob(u_char *data + char *chost) + { + Buffer b; +- char *p; ++ char *p, *r; + u_int len; + int fail = 0; + +@@ -1186,6 +1216,8 @@ monitor_valid_hostbasedblob(u_char *data + if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) + fail++; + p = buffer_get_string(&b, NULL); ++ if ((r = strchr(p, '/')) != NULL) ++ *r = '\0'; + if (strcmp(authctxt->user, p) != 0) { + logit("wrong user name passed to monitor: expected %s != %.100s", + authctxt->user, p); +diff -up openssh-5.8p1/monitor.h.role openssh-5.8p1/monitor.h +--- openssh-5.8p1/monitor.h.role 2011-02-12 14:34:11.000000000 +0100 ++++ openssh-5.8p1/monitor.h 2011-02-12 14:34:11.000000000 +0100 +@@ -31,6 +31,9 @@ + enum monitor_reqtype { + MONITOR_REQ_MODULI, MONITOR_ANS_MODULI, + MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV, ++#ifdef WITH_SELINUX ++ MONITOR_REQ_AUTHROLE, ++#endif + MONITOR_REQ_SIGN, MONITOR_ANS_SIGN, + MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM, + MONITOR_REQ_AUTH2_READ_BANNER, MONITOR_ANS_AUTH2_READ_BANNER, +diff -up openssh-5.8p1/monitor_wrap.c.role openssh-5.8p1/monitor_wrap.c +--- openssh-5.8p1/monitor_wrap.c.role 2011-02-12 14:34:11.000000000 +0100 ++++ openssh-5.8p1/monitor_wrap.c 2011-02-12 14:34:11.000000000 +0100 +@@ -298,6 +298,25 @@ mm_inform_authserv(char *service, char * + buffer_free(&m); + } + ++/* Inform the privileged process about role */ ++ ++#ifdef WITH_SELINUX ++void ++mm_inform_authrole(char *role) ++{ ++ Buffer m; ++ ++ debug3("%s entering", __func__); ++ ++ buffer_init(&m); ++ buffer_put_cstring(&m, role ? role : ""); ++ ++ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, &m); ++ ++ buffer_free(&m); ++} ++#endif ++ + /* Do the password authentication */ + int + mm_auth_password(Authctxt *authctxt, char *password) +diff -up openssh-5.8p1/monitor_wrap.h.role openssh-5.8p1/monitor_wrap.h +--- openssh-5.8p1/monitor_wrap.h.role 2011-02-12 14:34:11.000000000 +0100 ++++ openssh-5.8p1/monitor_wrap.h 2011-02-12 14:34:11.000000000 +0100 +@@ -41,6 +41,9 @@ int mm_is_monitor(void); + DH *mm_choose_dh(int, int, int); + int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int); + void mm_inform_authserv(char *, char *); ++#ifdef WITH_SELINUX ++void mm_inform_authrole(char *); ++#endif + struct passwd *mm_getpwnamallow(const char *); + char *mm_auth2_read_banner(void); + int mm_auth_password(struct Authctxt *, char *); +diff -up openssh-5.8p1/openbsd-compat/Makefile.in.role openssh-5.8p1/openbsd-compat/Makefile.in +--- openssh-5.8p1/openbsd-compat/Makefile.in.role 2010-10-07 13:19:24.000000000 +0200 ++++ openssh-5.8p1/openbsd-compat/Makefile.in 2011-02-12 14:34:11.000000000 +0100 +@@ -20,7 +20,7 @@ OPENBSD=base64.o basename.o bindresvport + + COMPAT=bsd-arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o + +-PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o ++PORTS=port-aix.o port-irix.o port-linux.o port-linux_part_2.o port-solaris.o port-tun.o port-uw.o + + .c.o: + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< +diff -up openssh-5.8p1/openbsd-compat/port-linux.c.role openssh-5.8p1/openbsd-compat/port-linux.c +--- openssh-5.8p1/openbsd-compat/port-linux.c.role 2011-02-12 14:34:11.000000000 +0100 ++++ openssh-5.8p1/openbsd-compat/port-linux.c 2011-02-12 14:37:31.000000000 +0100 +@@ -31,48 +31,73 @@ + + #include "log.h" + #include "xmalloc.h" ++#include "servconf.h" + #include "port-linux.h" ++#include "key.h" ++#include "hostfile.h" ++#include "auth.h" + + #ifdef WITH_SELINUX + #include + #include + #include + +-/* Wrapper around is_selinux_enabled() to log its return value once only */ +-int +-ssh_selinux_enabled(void) +-{ +- static int enabled = -1; ++extern ServerOptions options; ++extern Authctxt *the_authctxt; ++extern int inetd_flag; ++extern int rexeced_flag; + +- if (enabled == -1) { +- enabled = (is_selinux_enabled() == 1); +- debug("SELinux support %s", enabled ? "enabled" : "disabled"); ++static void ++ssh_selinux_get_role_level(char **role, const char **level) ++{ ++ *role = NULL; ++ *level = NULL; ++ if (the_authctxt) { ++ if (the_authctxt->role != NULL) { ++ char *slash; ++ *role = xstrdup(the_authctxt->role); ++ if ((slash = strchr(*role, '/')) != NULL) { ++ *slash = '\0'; ++ *level = slash + 1; ++ } ++ } + } +- +- return (enabled); + } + + /* Return the default security context for the given username */ + static security_context_t + ssh_selinux_getctxbyname(char *pwname) + { +- security_context_t sc; +- char *sename = NULL, *lvl = NULL; +- int r; ++ security_context_t sc = NULL; ++ char *sename, *lvl; ++ char *role; ++ const char *reqlvl; ++ int r = 0; + ++ ssh_selinux_get_role_level(&role, &reqlvl); + #ifdef HAVE_GETSEUSERBYNAME +- if (getseuserbyname(pwname, &sename, &lvl) != 0) +- return NULL; ++ if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) { ++ sename = NULL; ++ lvl = NULL; ++ } + #else + sename = pwname; + lvl = NULL; + #endif + ++ if (r == 0) { + #ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL +- r = get_default_context_with_level(sename, lvl, NULL, &sc); ++ if (role != NULL && role[0]) ++ r = get_default_context_with_rolelevel(sename, role, lvl, NULL, &sc); ++ else ++ r = get_default_context_with_level(sename, lvl, NULL, &sc); + #else +- r = get_default_context(sename, NULL, &sc); ++ if (role != NULL && role[0]) ++ r = get_default_context_with_role(sename, role, NULL, &sc); ++ else ++ r = get_default_context(sename, NULL, &sc); + #endif ++ } + + if (r != 0) { + switch (security_getenforce()) { +@@ -100,6 +125,36 @@ ssh_selinux_getctxbyname(char *pwname) + return (sc); + } + ++/* Setup environment variables for pam_selinux */ ++static int ++ssh_selinux_setup_pam_variables(void) ++{ ++ const char *reqlvl; ++ char *role; ++ char *use_current; ++ int rv; ++ ++ debug3("%s: setting execution context", __func__); ++ ++ ssh_selinux_get_role_level(&role, &reqlvl); ++ ++ rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : ""); ++ ++ if (inetd_flag && !rexeced_flag) { ++ use_current = "1"; ++ } else { ++ use_current = ""; ++ rv = rv || do_pam_putenv("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: ""); ++ } ++ ++ rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current); ++ ++ if (role != NULL) ++ xfree(role); ++ ++ return rv; ++} ++ + /* Set the execution context to the default for the specified user */ + void + ssh_selinux_setup_exec_context(char *pwname) +@@ -109,6 +164,24 @@ ssh_selinux_setup_exec_context(char *pwn + if (!ssh_selinux_enabled()) + return; + ++ if (options.use_pam) { ++ /* do not compute context, just setup environment for pam_selinux */ ++ if (ssh_selinux_setup_pam_variables()) { ++ switch (security_getenforce()) { ++ case -1: ++ fatal("%s: security_getenforce() failed", __func__); ++ case 0: ++ error("%s: SELinux PAM variable setup failure. Continuing in permissive mode.", ++ __func__); ++ break; ++ default: ++ fatal("%s: SELinux PAM variable setup failure. Aborting connection.", ++ __func__); ++ } ++ } ++ return; ++ } ++ + debug3("%s: setting execution context", __func__); + + user_ctx = ssh_selinux_getctxbyname(pwname); +@@ -206,21 +279,6 @@ ssh_selinux_change_context(const char *n + xfree(newctx); + } + +-void +-ssh_selinux_setfscreatecon(const char *path) +-{ +- security_context_t context; +- +- if (!ssh_selinux_enabled()) +- return; +- if (path == NULL) { +- setfscreatecon(NULL); +- return; +- } +- if (matchpathcon(path, 0700, &context) == 0) +- setfscreatecon(context); +-} +- + #endif /* WITH_SELINUX */ + + #ifdef LINUX_OOM_ADJUST +diff -up openssh-5.8p1/openbsd-compat/port-linux_part_2.c.role openssh-5.8p1/openbsd-compat/port-linux_part_2.c +--- openssh-5.8p1/openbsd-compat/port-linux_part_2.c.role 2011-02-12 14:34:11.000000000 +0100 ++++ openssh-5.8p1/openbsd-compat/port-linux_part_2.c 2011-02-12 14:34:11.000000000 +0100 +@@ -0,0 +1,75 @@ ++/* $Id: port-linux.c,v 1.11.4.2 2011/02/04 00:43:08 djm Exp $ */ ++ ++/* ++ * Copyright (c) 2005 Daniel Walsh ++ * Copyright (c) 2006 Damien Miller ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++/* ++ * Linux-specific portability code - just SELinux support at present ++ */ ++ ++#include "includes.h" ++ ++#if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST) ++#include ++#include ++#include ++#include ++ ++#include "log.h" ++#include "xmalloc.h" ++#include "port-linux.h" ++#include "key.h" ++#include "hostfile.h" ++#include "auth.h" ++ ++#ifdef WITH_SELINUX ++#include ++#include ++#include ++ ++/* Wrapper around is_selinux_enabled() to log its return value once only */ ++int ++ssh_selinux_enabled(void) ++{ ++ static int enabled = -1; ++ ++ if (enabled == -1) { ++ enabled = (is_selinux_enabled() == 1); ++ debug("SELinux support %s", enabled ? "enabled" : "disabled"); ++ } ++ ++ return (enabled); ++} ++ ++void ++ssh_selinux_setfscreatecon(const char *path) ++{ ++ security_context_t context; ++ ++ if (!ssh_selinux_enabled()) ++ return; ++ if (path == NULL) { ++ setfscreatecon(NULL); ++ return; ++ } ++ if (matchpathcon(path, 0700, &context) == 0) ++ setfscreatecon(context); ++} ++ ++#endif /* WITH_SELINUX */ ++ ++#endif /* WITH_SELINUX || LINUX_OOM_ADJUST */ diff --git a/openssh-5.8p1-selinux.patch b/openssh-5.8p1-selinux.patch new file mode 100644 index 0000000..6967cbd --- /dev/null +++ b/openssh-5.8p1-selinux.patch @@ -0,0 +1,12 @@ +diff -up openssh-5.8p1/openbsd-compat/port-linux.c.selinux openssh-5.8p1/openbsd-compat/port-linux.c +--- openssh-5.8p1/openbsd-compat/port-linux.c.selinux 2011-02-12 09:38:45.000000000 +0100 ++++ openssh-5.8p1/openbsd-compat/port-linux.c 2011-02-12 09:39:10.000000000 +0100 +@@ -213,7 +213,7 @@ ssh_selinux_setfscreatecon(const char *p + + if (!ssh_selinux_enabled()) + return; +- if (path == NULL) ++ if (path == NULL) { + setfscreatecon(NULL); + return; + } diff --git a/openssh-5.8p1-vendor.patch b/openssh-5.8p1-vendor.patch new file mode 100644 index 0000000..2e26d58 --- /dev/null +++ b/openssh-5.8p1-vendor.patch @@ -0,0 +1,159 @@ +diff -up openssh-5.8p1/configure.ac.vendor openssh-5.8p1/configure.ac +--- openssh-5.8p1/configure.ac.vendor 2011-02-04 01:42:14.000000000 +0100 ++++ openssh-5.8p1/configure.ac 2011-02-09 22:39:55.000000000 +0100 +@@ -4097,6 +4097,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 +@@ -4327,6 +4333,7 @@ echo " IP address in \$DISPLAY hac + echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" + echo " BSD Auth support: $BSD_AUTH_MSG" + echo " Random number source: $RAND_MSG" ++echo " Vendor patch level: $SSH_VENDOR_PATCHLEVEL" + if test ! -z "$USE_RAND_HELPER" ; then + echo " ssh-rand-helper collects from: $RAND_HELPER_MSG" + fi +diff -up openssh-5.8p1/servconf.c.vendor openssh-5.8p1/servconf.c +--- openssh-5.8p1/servconf.c.vendor 2010-11-20 05:19:38.000000000 +0100 ++++ openssh-5.8p1/servconf.c 2011-02-09 22:41:32.000000000 +0100 +@@ -123,6 +123,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; +@@ -281,7 +282,9 @@ 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) + use_privsep = 1; +@@ -319,7 +322,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, sAuthorizedKeysFile2, + sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, +@@ -432,6 +435,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 }, +@@ -1086,6 +1090,10 @@ process_server_config_line(ServerOptions + intptr = &use_privsep; + goto parse_flag; + ++ 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) +@@ -1726,6 +1734,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.8p1/servconf.h.vendor openssh-5.8p1/servconf.h +--- openssh-5.8p1/servconf.h.vendor 2010-11-20 05:19:38.000000000 +0100 ++++ openssh-5.8p1/servconf.h 2011-02-09 22:39:55.000000000 +0100 +@@ -134,6 +134,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.8p1/sshd_config.0.vendor openssh-5.8p1/sshd_config.0 +--- openssh-5.8p1/sshd_config.0.vendor 2011-02-09 22:39:54.000000000 +0100 ++++ openssh-5.8p1/sshd_config.0 2011-02-09 22:39:55.000000000 +0100 +@@ -535,6 +535,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.8p1/sshd_config.5.vendor openssh-5.8p1/sshd_config.5 +--- openssh-5.8p1/sshd_config.5.vendor 2011-02-09 22:39:54.000000000 +0100 ++++ openssh-5.8p1/sshd_config.5 2011-02-09 22:39:55.000000000 +0100 +@@ -931,6 +931,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.8p1/sshd_config.vendor openssh-5.8p1/sshd_config +--- openssh-5.8p1/sshd_config.vendor 2011-02-09 22:39:54.000000000 +0100 ++++ openssh-5.8p1/sshd_config 2011-02-09 22:39:55.000000000 +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.8p1/sshd.c.vendor openssh-5.8p1/sshd.c +--- openssh-5.8p1/sshd.c.vendor 2011-02-09 22:39:55.000000000 +0100 ++++ openssh-5.8p1/sshd.c 2011-02-09 22:39:55.000000000 +0100 +@@ -419,7 +419,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. */ +@@ -1550,7 +1550,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 62fa9d0..e2a1dc2 100644 --- a/openssh.spec +++ b/openssh.spec @@ -70,10 +70,10 @@ %endif # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 -%define openssh_ver 5.6p1 -%define openssh_rel 30 +%define openssh_ver 5.8p1 +%define openssh_rel 1 %define pam_ssh_agent_ver 0.9.2 -%define pam_ssh_agent_rel 29 +%define pam_ssh_agent_rel 30 Summary: An open source implementation of SSH protocol versions 1 and 2 Name: openssh @@ -96,49 +96,54 @@ Source5: pam_ssh_agent-rmheaders Patch100: openssh-5.6p1-wIm.patch Patch0: openssh-5.6p1-redhat.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1402 -Patch1: openssh-5.6p1-audit.patch -Patch2: openssh-5.6p1-audit1a.patch -Patch3: openssh-5.6p1-audit2.patch -Patch4: openssh-5.6p1-audit3.patch -Patch104: openssh-5.6p1-audit4.patch -Patch105: openssh-5.6p1-audit5.patch +Patch2: openssh-5.8p1-audit2.patch +Patch3: openssh-5.8p1-audit3.patch +Patch4: openssh-5.8p1-audit4.patch +Patch5: openssh-5.8p1-audit5.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1640 -Patch5: openssh-5.2p1-vendor.patch +Patch9: openssh-5.8p1-vendor.patch +# --- pam_ssh-agent --- Patch10: pam_ssh_agent_auth-0.9-build.patch Patch11: pam_ssh_agent_auth-0.9.2-seteuid.patch -#https://bugzilla.mindrot.org/show_bug.cgi?id=1641 -Patch12: openssh-5.4p1-selinux.patch -Patch13: openssh-5.6p1-mls.patch -Patch18: openssh-5.4p1-pam_selinux.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1663 -Patch20: openssh-5.6p1-authorized-keys-command.patch +Patch20: openssh-5.8p1-authorized-keys-command.patch Patch21: openssh-5.6p1-ldap.patch +#?mail-conf +Patch22: openssh-5.8p1-selinux.patch +#https://bugzilla.mindrot.org/show_bug.cgi?id=1641 +Patch23: openssh-5.8p1-selinux-role.patch +#? +Patch24: openssh-5.8p1-mls.patch +# #https://bugzilla.mindrot.org/show_bug.cgi?id=1614 +# Patch25: openssh-5.6p1-selabel.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1668 -Patch23: openssh-5.6p1-keygen.patch -Patch24: openssh-4.3p1-fromto-remote.patch -#https://bugzilla.mindrot.org/show_bug.cgi?id=1636 -Patch27: openssh-5.1p1-log-in-chroot.patch -Patch30: openssh-5.6p1-exit-deadlock.patch -Patch35: openssh-5.1p1-askpass-progress.patch -Patch38: openssh-4.3p2-askpass-grab-info.patch +Patch30: openssh-5.6p1-keygen.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1644 -Patch44: openssh-5.2p1-allow-ip-opts.patch -Patch49: openssh-4.3p2-gssapi-canohost.patch -Patch62: openssh-5.1p1-scp-manpage.patch -Patch65: openssh-5.6p1-fips.patch -#https://bugzilla.mindrot.org/show_bug.cgi?id=1614 -Patch69: openssh-5.6p1-selabel.patch -Patch71: openssh-5.2p1-edns.patch -Patch73: openssh-5.6p1-gsskex.patch +Patch31: openssh-5.2p1-allow-ip-opts.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1701 -Patch74: openssh-5.3p1-randclean.patch +Patch32: openssh-5.8p1-randclean.patch +# #https://bugzilla.mindrot.org/show_bug.cgi?id=1636 +# Patch33: openssh-5.1p1-log-in-chroot.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1780 -Patch78: openssh-5.6p1-kuserok.patch -Patch79: openssh-5.5p1-x11.patch -#https://bugzilla.mindrot.org/show_bug.cgi?id=1817 -Patch80: openssh-5.6p1-biguid.patch -#https://bugzilla.mindrot.org/show_bug.cgi?id=1842 -Patch81: openssh-5.6p1-clientloop.patch +Patch34: openssh-5.8p1-kuserok.patch +#? +Patch50: openssh-5.8p1-fips.patch +#? +Patch51: openssh-5.5p1-x11.patch +#? +Patch52: openssh-5.6p1-exit-deadlock.patch +#? +Patch53: openssh-5.1p1-askpass-progress.patch +#? +Patch54: openssh-4.3p2-askpass-grab-info.patch +#? +Patch56: openssh-5.2p1-edns.patch +#? +Patch57: openssh-5.1p1-scp-manpage.patch +#http://www.sxw.org.uk/computing/patches/openssh.html +Patch60: openssh-5.8p1-gsskex.patch +#? +Patch61: openssh-5.8p1-gssapi-canohost.patch License: BSD Group: Applications/Internet @@ -278,14 +283,11 @@ The module is most useful for su and sudo service stacks. #Do not enable by default ###%patch100 -p1 -b .wIm %patch0 -p1 -b .redhat -%patch1 -p1 -b .audit -%patch2 -p1 -b .audit1a -%patch3 -p1 -b .audit2 -%patch4 -p1 -b .audit3 -%patch104 -p1 -b .audit4 -%patch105 -p1 -b .audit5 -%patch5 -p1 -b .vendor - +%patch2 -p1 -b .audit2 +%patch3 -p1 -b .audit3 +%patch4 -p1 -b .audit4 +%patch5 -p1 -b .audit5 +%patch9 -p1 -b .vendor %if %{pam_ssh_agent} pushd pam_ssh_agent_auth-%{pam_ssh_agent_ver} %patch10 -p1 -b .psaa-build @@ -294,34 +296,27 @@ pushd pam_ssh_agent_auth-%{pam_ssh_agent_ver} rm -f $(cat %{SOURCE5}) popd %endif - +%patch20 -p1 -b .akc +%patch21 -p1 -b .ldap %if %{WITH_SELINUX} #SELinux -%patch12 -p1 -b .selinux -%patch13 -p1 -b .mls -%patch18 -p1 -b .pam_selinux +%patch22 -p1 -b .selinux +%patch23 -p1 -b .role +%patch24 -p1 -b .mls %endif - -%patch20 -p1 -b .akc -%patch21 -p1 -b .ldap -%patch23 -p1 -b .keygen -%patch24 -p1 -b .fromto-remote -%patch27 -p1 -b .log-chroot -%patch30 -p1 -b .exit-deadlock -%patch35 -p1 -b .progress -%patch38 -p1 -b .grab-info -%patch44 -p1 -b .ip-opts -%patch49 -p1 -b .canohost -%patch62 -p1 -b .manpage -%patch65 -p1 -b .fips -%patch69 -p1 -b .selabel -%patch71 -p1 -b .edns -%patch73 -p1 -b .gsskex -%patch74 -p1 -b .randclean -%patch78 -p1 -b .kuserok -%patch79 -p1 -b .x11 -%patch80 -p1 -b .biguid -%patch81 -p1 -b .clientloop +%patch30 -p1 -b .keygen +%patch31 -p1 -b .ip-opts +%patch32 -p1 -b .randclean +%patch34 -p1 -b .kuserok +%patch50 -p1 -b .fips +%patch51 -p1 -b .x11 +%patch52 -p1 -b .exit-deadlock +%patch53 -p1 -b .progress +%patch54 -p1 -b .grab-info +%patch56 -p1 -b .edns +%patch57 -p1 -b .manpage +%patch60 -p1 -b .gsskex +%patch61 -p1 -b .canohost autoreconf pushd pam_ssh_agent_auth-%{pam_ssh_agent_ver} @@ -339,9 +334,13 @@ CFLAGS="$CFLAGS -fPIC" %else CFLAGS="$CFLAGS -fpic" %endif -export CFLAGS SAVE_LDFLAGS="$LDFLAGS" -LDFLAGS="$LDFLAGS -pie -z relro -z now"; export LDFLAGS +LDFLAGS="$LDFLAGS -pie -z relro -z now" + +export CFLAGS +export LDFLAGS + + %endif %if %{kerberos5} if test -r /etc/profile.d/krb5-devel.sh ; then @@ -603,6 +602,9 @@ fi %endif %changelog +* Mon Feb 14 2011 Jan F. Chadima - 5.8p1-1 + 0.9.2-30 +- bump openssh version to 5.8p1 + * Tue Feb 08 2011 Fedora Release Engineering - 5.6p1-30.1 - Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild diff --git a/sources b/sources index 0654206..de9e9e4 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -acf3e8e40ca5c8b7174202dbe4c4e76b openssh-5.6p1-noacss.tar.bz2 +9ada688cb55f609e7b360177f25e89bd openssh-5.8p1-noacss.tar.bz2 b68f1c385d7885fbe2c3626bf77aa3d6 pam_ssh_agent_auth-0.9.2.tar.bz2