ignore SIGPIPE in ssh keyscan

This commit is contained in:
Jan F. Chadima 2011-09-07 15:12:54 +02:00
parent 19d4c790a8
commit 69dd72f6ef
25 changed files with 11966 additions and 132 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ pam_ssh_agent_auth-0.9.2.tar.bz2
/pam_ssh_agent_auth-0.9.2.tar.bz2
/openssh-5.8p1-noacss.tar.bz2
/openssh-5.8p2-noacss.tar.bz2
/openssh-5.9p1-noacss.tar.bz2

446
openssh-5.9p1-2auth.patch Normal file
View File

@ -0,0 +1,446 @@
diff -up openssh-5.9p0/auth.h.2auth openssh-5.9p0/auth.h
--- openssh-5.9p0/auth.h.2auth 2011-05-29 13:39:38.000000000 +0200
+++ openssh-5.9p0/auth.h 2011-09-05 13:16:00.550626991 +0200
@@ -149,6 +149,8 @@ int auth_root_allowed(char *);
char *auth2_read_banner(void);
+void userauth_restart(const char *);
+
void privsep_challenge_enable(void);
int auth2_challenge(Authctxt *, char *);
diff -up openssh-5.9p0/auth2.c.2auth openssh-5.9p0/auth2.c
--- openssh-5.9p0/auth2.c.2auth 2011-05-05 06:04:11.000000000 +0200
+++ openssh-5.9p0/auth2.c 2011-09-05 13:16:00.640626827 +0200
@@ -290,6 +290,23 @@ input_userauth_request(int type, u_int32
}
void
+userauth_restart(const char *method)
+{
+ options.two_factor_authentication = 0;
+
+ options.pubkey_authentication = options.second_pubkey_authentication && strcmp(method, method_pubkey.name);
+#ifdef GSSAPI
+ options.gss_authentication = options.second_gss_authentication && strcmp(method, method_gssapi.name);
+#endif
+#ifdef JPAKE
+ options.zero_knowledge_password_authentication = options.second_zero_knowledge_password_authentication && strcmp(method, method_jpake.name);
+#endif
+ options.password_authentication = options.second_password_authentication && strcmp(method, method_passwd.name);
+ options.kbd_interactive_authentication = options.second_kbd_interactive_authentication && strcmp(method, method_kbdint.name);
+ options.hostbased_authentication = options.second_hostbased_authentication && strcmp(method, method_hostbased.name);
+}
+
+void
userauth_finish(Authctxt *authctxt, int authenticated, char *method)
{
char *methods;
@@ -337,6 +354,15 @@ userauth_finish(Authctxt *authctxt, int
/* XXX todo: check if multiple auth methods are needed */
if (authenticated == 1) {
+ if (options.two_factor_authentication) {
+ userauth_restart(method);
+ if (use_privsep)
+ PRIVSEP(userauth_restart(method));
+
+ debug("1st factor authentication done go to 2nd factor");
+ goto ask_methods;
+ }
+
/* turn off userauth */
dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
packet_start(SSH2_MSG_USERAUTH_SUCCESS);
@@ -356,6 +382,7 @@ userauth_finish(Authctxt *authctxt, int
#endif
packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
}
+ask_methods:
methods = authmethods_get();
packet_start(SSH2_MSG_USERAUTH_FAILURE);
packet_put_cstring(methods);
diff -up openssh-5.9p0/monitor.c.2auth openssh-5.9p0/monitor.c
--- openssh-5.9p0/monitor.c.2auth 2011-08-05 22:15:18.000000000 +0200
+++ openssh-5.9p0/monitor.c 2011-09-05 13:37:35.468502112 +0200
@@ -165,6 +165,7 @@ int mm_answer_jpake_step1(int, Buffer *)
int mm_answer_jpake_step2(int, Buffer *);
int mm_answer_jpake_key_confirm(int, Buffer *);
int mm_answer_jpake_check_confirm(int, Buffer *);
+int mm_answer_userauth_restart(int, Buffer *);
#ifdef USE_PAM
int mm_answer_pam_start(int, Buffer *);
@@ -259,6 +260,7 @@ struct mon_table mon_dispatch_proto20[]
{MONITOR_REQ_JPAKE_KEY_CONFIRM, MON_ONCE, mm_answer_jpake_key_confirm},
{MONITOR_REQ_JPAKE_CHECK_CONFIRM, MON_AUTH, mm_answer_jpake_check_confirm},
#endif
+ {MONITOR_REQ_USERAUTH_RESTART, MON_PERMIT, mm_answer_userauth_restart},
{0, 0, NULL}
};
@@ -378,9 +380,9 @@ monitor_child_preauth(Authctxt *_authctx
}
/* The first few requests do not require asynchronous access */
- while (!authenticated) {
+ while (!authenticated || options.two_factor_authentication) {
auth_method = "unknown";
authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
if (authenticated) {
if (!(ent->flags & MON_AUTHDECIDE))
fatal("%s: unexpected authentication from %d",
@@ -390,7 +393,7 @@ monitor_child_preauth(Authctxt *_authctx
authenticated = 0;
#ifdef USE_PAM
/* PAM needs to perform account checks after auth */
- if (options.use_pam && authenticated) {
+ if (options.use_pam && authenticated && !options.two_factor_authentication) {
Buffer m;
buffer_init(&m);
@@ -2000,6 +2006,19 @@ monitor_reinit(struct monitor *mon)
monitor_openfds(mon, 0);
}
+int
+mm_answer_userauth_restart(int sock, Buffer *m)
+{
+ char *method;
+ u_int method_len;
+
+ method = buffer_get_string(m, &method_len);
+
+ userauth_restart(method);
+
+ mm_request_send(sock, MONITOR_ANS_USERAUTH_RESTART, m);
+}
+
#ifdef GSSAPI
int
mm_answer_gss_setup_ctx(int sock, Buffer *m)
diff -up openssh-5.9p0/monitor.h.2auth openssh-5.9p0/monitor.h
--- openssh-5.9p0/monitor.h.2auth 2011-06-20 06:42:23.000000000 +0200
+++ openssh-5.9p0/monitor.h 2011-09-05 13:16:00.855502353 +0200
@@ -66,6 +66,7 @@ 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_USERAUTH_RESTART, MONITOR_ANS_USERAUTH_RESTART,
};
struct mm_master;
diff -up openssh-5.9p0/monitor_wrap.c.2auth openssh-5.9p0/monitor_wrap.c
--- openssh-5.9p0/monitor_wrap.c.2auth 2011-06-20 06:42:23.000000000 +0200
+++ openssh-5.9p0/monitor_wrap.c 2011-09-05 13:16:00.968503257 +0200
@@ -1173,6 +1173,26 @@ mm_auth_rsa_verify_response(Key *key, BI
return (success);
}
+void
+mm_userauth_restart(const char *monitor)
+{
+ Buffer m;
+
+ debug3("%s entering", __func__);
+
+ buffer_init(&m);
+
+ buffer_put_cstring(&m, monitor);
+
+ mm_request_send(pmonitor->m_recvfd,
+ MONITOR_REQ_USERAUTH_RESTART, &m);
+ debug3("%s: waiting for MONITOR_ANS_USERAUTH_RESTART", __func__);
+ mm_request_receive_expect(pmonitor->m_recvfd,
+ MONITOR_ANS_USERAUTH_RESTART, &m);
+
+ buffer_free(&m);
+}
+
#ifdef SSH_AUDIT_EVENTS
void
mm_audit_event(ssh_audit_event_t event)
diff -up openssh-5.9p0/monitor_wrap.h.2auth openssh-5.9p0/monitor_wrap.h
--- openssh-5.9p0/monitor_wrap.h.2auth 2011-06-20 06:42:23.000000000 +0200
+++ openssh-5.9p0/monitor_wrap.h 2011-09-05 13:16:01.074502211 +0200
@@ -53,6 +53,7 @@ int mm_key_verify(Key *, u_char *, u_int
int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *);
BIGNUM *mm_auth_rsa_generate_challenge(Key *);
+void mm_userauth_restart(const char *);
#ifdef GSSAPI
OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
diff -up openssh-5.9p0/servconf.c.2auth openssh-5.9p0/servconf.c
--- openssh-5.9p0/servconf.c.2auth 2011-06-23 00:30:03.000000000 +0200
+++ openssh-5.9p0/servconf.c 2011-09-05 13:16:01.223441110 +0200
@@ -92,6 +92,13 @@ initialize_server_options(ServerOptions
options->hostbased_uses_name_from_packet_only = -1;
options->rsa_authentication = -1;
options->pubkey_authentication = -1;
+ options->two_factor_authentication = -1;
+ options->second_pubkey_authentication = -1;
+ options->second_gss_authentication = -1;
+ options->second_password_authentication = -1;
+ options->second_kbd_interactive_authentication = -1;
+ options->second_zero_knowledge_password_authentication = -1;
+ options->second_hostbased_authentication = -1;
options->kerberos_authentication = -1;
options->kerberos_or_local_passwd = -1;
options->kerberos_ticket_cleanup = -1;
@@ -237,6 +244,20 @@ fill_default_server_options(ServerOption
options->permit_empty_passwd = 0;
if (options->permit_user_env == -1)
options->permit_user_env = 0;
+ if (options->two_factor_authentication == -1)
+ options->two_factor_authentication = 0;
+ if (options->second_pubkey_authentication == -1)
+ options->second_pubkey_authentication = 1;
+ if (options->second_gss_authentication == -1)
+ options->second_gss_authentication = 0;
+ if (options->second_password_authentication == -1)
+ options->second_password_authentication = 1;
+ if (options->second_kbd_interactive_authentication == -1)
+ options->second_kbd_interactive_authentication = 0;
+ if (options->second_zero_knowledge_password_authentication == -1)
+ options->second_zero_knowledge_password_authentication = 0;
+ if (options->second_hostbased_authentication == -1)
+ options->second_hostbased_authentication = 0;
if (options->use_login == -1)
options->use_login = 0;
if (options->compression == -1)
@@ -316,8 +337,11 @@ typedef enum {
sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
sMaxStartups, sMaxAuthTries, sMaxSessions,
sBanner, sUseDNS, sHostbasedAuthentication,
- sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
- sClientAliveCountMax, sAuthorizedKeysFile,
+ sHostbasedUsesNameFromPacketOnly, sTwoFactorAuthentication,
+ sSecondPubkeyAuthentication, sSecondGssAuthentication,
+ sSecondPasswordAuthentication, sSecondKbdInteractiveAuthentication,
+ sSecondZeroKnowledgePasswordAuthentication, sSecondHostbasedAuthentication,
+ sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
sUsePrivilegeSeparation, sAllowAgentForwarding,
@@ -395,6 +419,21 @@ static struct {
#else
{ "zeroknowledgepasswordauthentication", sUnsupported, SSHCFG_ALL },
#endif
+ { "twofactorauthentication", sTwoFactorAuthentication, SSHCFG_ALL },
+ { "secondpubkeyauthentication", sSecondPubkeyAuthentication, SSHCFG_ALL },
+#ifdef GSSAPI
+ { "secondgssapiauthentication", sSecondGssAuthentication, SSHCFG_ALL },
+#else
+ { "secondgssapiauthentication", sUnsupported, SSHCFG_ALL },
+#endif
+ { "secondpasswordauthentication", sSecondPasswordAuthentication, SSHCFG_ALL },
+ { "secondkbdinteractiveauthentication", sSecondKbdInteractiveAuthentication, SSHCFG_ALL },
+#ifdef JPAKE
+ { "secondzeroknowledgepasswordauthentication", sSecondZeroKnowledgePasswordAuthentication, SSHCFG_ALL },
+#else
+ { "secondzeroknowledgepasswordauthentication", sUnsupported, SSHCFG_ALL },
+#endif
+ { "secondhostbasedauthentication", sSecondHostbasedAuthentication, SSHCFG_ALL },
{ "checkmail", sDeprecated, SSHCFG_GLOBAL },
{ "listenaddress", sListenAddress, SSHCFG_GLOBAL },
{ "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
@@ -982,6 +1021,34 @@ process_server_config_line(ServerOptions
intptr = &options->challenge_response_authentication;
goto parse_flag;
+ case sTwoFactorAuthentication:
+ intptr = &options->two_factor_authentication;
+ goto parse_flag;
+
+ case sSecondPubkeyAuthentication:
+ intptr = &options->second_pubkey_authentication;
+ goto parse_flag;
+
+ case sSecondGssAuthentication:
+ intptr = &options->second_gss_authentication;
+ goto parse_flag;
+
+ case sSecondPasswordAuthentication:
+ intptr = &options->second_password_authentication;
+ goto parse_flag;
+
+ case sSecondKbdInteractiveAuthentication:
+ intptr = &options->second_kbd_interactive_authentication;
+ goto parse_flag;
+
+ case sSecondZeroKnowledgePasswordAuthentication:
+ intptr = &options->second_zero_knowledge_password_authentication;
+ goto parse_flag;
+
+ case sSecondHostbasedAuthentication:
+ intptr = &options->second_hostbased_authentication;
+ goto parse_flag;
+
case sPrintMotd:
intptr = &options->print_motd;
goto parse_flag;
@@ -1491,14 +1558,21 @@ void
copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
{
M_CP_INTOPT(password_authentication);
+ M_CP_INTOPT(second_password_authentication);
M_CP_INTOPT(gss_authentication);
+ M_CP_INTOPT(second_gss_authentication);
M_CP_INTOPT(rsa_authentication);
M_CP_INTOPT(pubkey_authentication);
+ M_CP_INTOPT(second_pubkey_authentication);
M_CP_INTOPT(kerberos_authentication);
M_CP_INTOPT(hostbased_authentication);
+ M_CP_INTOPT(second_hostbased_authentication);
M_CP_INTOPT(hostbased_uses_name_from_packet_only);
M_CP_INTOPT(kbd_interactive_authentication);
+ M_CP_INTOPT(second_kbd_interactive_authentication);
M_CP_INTOPT(zero_knowledge_password_authentication);
+ M_CP_INTOPT(second_zero_knowledge_password_authentication);
+ M_CP_INTOPT(two_factor_authentication);
M_CP_INTOPT(permit_root_login);
M_CP_INTOPT(permit_empty_passwd);
@@ -1720,17 +1794,24 @@ dump_config(ServerOptions *o)
#endif
#ifdef GSSAPI
dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
+ dump_cfg_fmtint(sSecondGssAuthentication, o->second_gss_authentication);
dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
#endif
#ifdef JPAKE
dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication,
o->zero_knowledge_password_authentication);
+ dump_cfg_fmtint(sSecondZeroKnowledgePasswordAuthentication,
+ o->second_zero_knowledge_password_authentication);
#endif
dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
+ dump_cfg_fmtint(sSecondPasswordAuthentication, o->second_password_authentication);
dump_cfg_fmtint(sKbdInteractiveAuthentication,
o->kbd_interactive_authentication);
+ dump_cfg_fmtint(sSecondKbdInteractiveAuthentication,
+ o->second_kbd_interactive_authentication);
dump_cfg_fmtint(sChallengeResponseAuthentication,
o->challenge_response_authentication);
+ dump_cfg_fmtint(sTwoFactorAuthentication, o->two_factor_authentication);
dump_cfg_fmtint(sPrintMotd, o->print_motd);
dump_cfg_fmtint(sPrintLastLog, o->print_lastlog);
dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding);
diff -up openssh-5.9p0/servconf.h.2auth openssh-5.9p0/servconf.h
--- openssh-5.9p0/servconf.h.2auth 2011-06-23 00:30:03.000000000 +0200
+++ openssh-5.9p0/servconf.h 2011-09-05 13:16:01.352564530 +0200
@@ -112,6 +112,14 @@ typedef struct {
/* If true, permit jpake auth */
int permit_empty_passwd; /* If false, do not permit empty
* passwords. */
+ int two_factor_authentication; /* If true, the first sucessful authentication
+ * will be followed by the second one from anorher set */
+ int second_pubkey_authentication; /* second set of authentications */
+ int second_gss_authentication;
+ int second_password_authentication;
+ int second_kbd_interactive_authentication;
+ int second_zero_knowledge_password_authentication;
+ int second_hostbased_authentication;
int permit_user_env; /* If true, read ~/.ssh/environment */
int use_login; /* If true, login(1) is used */
int compression; /* If true, compression is allowed */
diff -up openssh-5.9p0/sshd_config.2auth openssh-5.9p0/sshd_config
--- openssh-5.9p0/sshd_config.2auth 2011-05-29 13:39:39.000000000 +0200
+++ openssh-5.9p0/sshd_config 2011-09-05 13:16:01.461565750 +0200
@@ -87,6 +87,13 @@ AuthorizedKeysFile .ssh/authorized_keys
# and ChallengeResponseAuthentication to 'no'.
#UsePAM no
+#TwoFactorAuthentication no
+#SecondPubkeyAuthentication yes
+#SecondHostbasedAuthentication no
+#SecondPasswordAuthentication yes
+#SecondChallengeResponseAuthentication yes
+#SecondGSSAPIAuthentication no
+
#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
diff -up openssh-5.9p0/sshd_config.5.2auth openssh-5.9p0/sshd_config.5
--- openssh-5.9p0/sshd_config.5.2auth 2011-08-05 22:17:33.000000000 +0200
+++ openssh-5.9p0/sshd_config.5 2011-09-05 13:16:01.572564496 +0200
@@ -726,6 +726,12 @@ Available keywords are
.Cm PubkeyAuthentication ,
.Cm RhostsRSAAuthentication ,
.Cm RSAAuthentication ,
+.Cm SecondGSSAPIAuthentication ,
+.Cm SecondHostbasedAuthentication ,
+.Cm SecondKbdInteractiveAuthentication ,
+.Cm SecondPasswordAuthentication ,
+.Cm SecondPubkeyAuthentication ,
+.Cm TwoFactorAuthentication ,
.Cm X11DisplayOffset ,
.Cm X11Forwarding
and
@@ -931,6 +937,41 @@ Specifies whether pure RSA authenticatio
The default is
.Dq yes .
This option applies to protocol version 1 only.
+.It Cm SecondGSSAPIAuthentication
+Specifies whether the
+.Cm GSSAPIAuthentication
+may be used on the second authentication while
+.Cm TwoFactorAuthentication
+is set.
+The argument must be “yes” or “no”. The default is “no”.
+.It Cm SecondHostbasedAuthentication
+Specifies whether the
+.Cm HostbasedAuthentication
+may be used on the second authentication while
+.Cm TwoFactorAuthentication
+is set.
+The argument must be “yes” or “no”. The default is “no”.
+.It Cm SecondKbdInteractiveAuthentication
+Specifies whether the
+.Cm KbdInteractiveAuthentication
+may be used on the second authentication while
+.Cm TwoFactorAuthentication
+is set.
+The argument must be “yes” or “no”. The default is “no”.
+.It Cm SecondPasswordAuthentication
+Specifies whether the
+.Cm PasswordAuthentication
+may be used on the second authentication while
+.Cm TwoFactorAuthentication
+is set.
+The argument must be “yes” or “no”. The default is “yes”.
+.It Cm SecondPubkeyAuthentication
+Specifies whether the
+.Cm PubkeyAuthentication
+may be used on the second authentication while
+.Cm TwoFactorAuthentication
+is set.
+The argument must be “yes” or “no”. The default is “yes”.
.It Cm ServerKeyBits
Defines the number of bits in the ephemeral protocol version 1 server key.
The minimum value is 512, and the default is 1024.
@@ -1011,6 +1052,22 @@ For more details on certificates, see th
.Sx CERTIFICATES
section in
.Xr ssh-keygen 1 .
+.It Cm TwoFactorAuthentication
+Specifies whether for a successful login is necessary to meet two independent authentications.
+If select the first method is selected from the set of allowed methods from
+.Cm GSSAPIAuthentication ,
+.Cm HostbasedAuthentication ,
+.Cm KbdInteractiveAuthentication ,
+.Cm PasswordAuthentication ,
+.Cm PubkeyAuthentication .
+And the second method is selected from the set of allowed methods from
+.Cm SecondGSSAPIAuthentication ,
+.Cm SecondHostbasedAuthentication ,
+.Cm SecondKbdInteractiveAuthentication ,
+.Cm SecondPasswordAuthentication ,
+.Cm SecondPubkeyAuthentication
+without the method used for the first authentication.
+The argument must be “yes” or “no”. The default is “no”.
.It Cm UseDNS
Specifies whether
.Xr sshd 8

436
openssh-5.9p1-akc.patch Normal file
View File

@ -0,0 +1,436 @@
diff -up openssh-5.9p0/auth2-pubkey.c.akc openssh-5.9p0/auth2-pubkey.c
--- openssh-5.9p0/auth2-pubkey.c.akc 2011-09-05 14:26:19.008627855 +0200
+++ openssh-5.9p0/auth2-pubkey.c 2011-09-05 14:26:21.125500355 +0200
@@ -27,6 +27,7 @@
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/wait.h>
#include <fcntl.h>
#include <pwd.h>
@@ -276,27 +277,15 @@ match_principals_file(char *file, struct
/* return 1 if user allows given key */
static int
-user_key_allowed2(struct passwd *pw, Key *key, char *file)
+user_search_key_in_file(FILE *f, char *file, Key* key, struct passwd *pw)
{
char line[SSH_MAX_PUBKEY_BYTES];
const char *reason;
int found_key = 0;
- FILE *f;
u_long linenum = 0;
Key *found;
char *fp;
- /* Temporarily use the user's uid. */
- temporarily_use_uid(pw);
-
- debug("trying public key file %s", file);
- f = auth_openkeyfile(file, pw, options.strict_modes);
-
- if (!f) {
- restore_uid();
- return 0;
- }
-
found_key = 0;
found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
@@ -389,8 +378,6 @@ user_key_allowed2(struct passwd *pw, Key
break;
}
}
- restore_uid();
- fclose(f);
key_free(found);
if (!found_key)
debug2("key not found");
@@ -452,7 +439,179 @@ 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 <AuthorizedKeysCommand or .ssh/authorized_keys* */
int
user_key_allowed(struct passwd *pw, Key *key)
{
diff -up openssh-5.9p0/configure.ac.akc openssh-5.9p0/configure.ac
--- openssh-5.9p0/configure.ac.akc 2011-08-18 06:48:24.000000000 +0200
+++ openssh-5.9p0/configure.ac 2011-09-05 14:26:21.227601590 +0200
@@ -1421,6 +1421,18 @@ AC_ARG_WITH([audit],
esac ]
)
+# Check whether user wants AuthorizedKeysCommand support
+AKC_MSG="no"
+AC_ARG_WITH(authorized-keys-command,
+ [ --with-authorized-keys-command Enable AuthorizedKeysCommand support],
+ [
+ if test "x$withval" != "xno" ; then
+ AC_DEFINE([WITH_AUTHORIZED_KEYS_COMMAND], 1, [Enable AuthorizedKeysCommand support])
+ AKC_MSG="yes"
+ fi
+ ]
+)
+
dnl Checks for library functions. Please keep in alphabetical order
AC_CHECK_FUNCS([ \
arc4random \
@@ -4235,6 +4247,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.9p0/servconf.c.akc openssh-5.9p0/servconf.c
--- openssh-5.9p0/servconf.c.akc 2011-09-05 14:26:08.430440620 +0200
+++ openssh-5.9p0/servconf.c 2011-09-05 14:26:21.386571209 +0200
@@ -139,6 +139,8 @@ initialize_server_options(ServerOptions
options->num_permitted_opens = -1;
options->adm_forced_command = NULL;
options->chroot_directory = NULL;
+ options->authorized_keys_command = NULL;
+ options->authorized_keys_command_runas = NULL;
options->zero_knowledge_password_authentication = -1;
options->revoked_keys_file = NULL;
options->trusted_user_ca_keys = NULL;
@@ -348,6 +350,7 @@ typedef enum {
sZeroKnowledgePasswordAuthentication, sHostCertificate,
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
sKexAlgorithms, sIPQoS,
+ sAuthorizedKeysCommand, sAuthorizedKeysCommandRunAs,
sDeprecated, sUnsupported
} ServerOpCodes;
@@ -487,6 +490,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 }
};
@@ -1462,6 +1472,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);
@@ -1573,6 +1597,8 @@ copy_set_server_options(ServerOptions *d
M_CP_INTOPT(zero_knowledge_password_authentication);
M_CP_INTOPT(second_zero_knowledge_password_authentication);
M_CP_INTOPT(two_factor_authentication);
+ M_CP_STROPT(authorized_keys_command);
+ M_CP_STROPT(authorized_keys_command_runas);
M_CP_INTOPT(permit_root_login);
M_CP_INTOPT(permit_empty_passwd);
@@ -1839,6 +1865,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.9p0/servconf.h.akc openssh-5.9p0/servconf.h
--- openssh-5.9p0/servconf.h.akc 2011-09-05 14:26:08.536478884 +0200
+++ openssh-5.9p0/servconf.h 2011-09-05 14:26:21.513500639 +0200
@@ -174,6 +174,8 @@ typedef struct {
char *revoked_keys_file;
char *trusted_user_ca_keys;
char *authorized_principals_file;
+ char *authorized_keys_command;
+ char *authorized_keys_command_runas;
} ServerOptions;
/*
diff -up openssh-5.9p0/sshd_config.0.akc openssh-5.9p0/sshd_config.0
--- openssh-5.9p0/sshd_config.0.akc 2011-08-29 16:30:02.000000000 +0200
+++ openssh-5.9p0/sshd_config.0 2011-09-05 14:26:21.880500451 +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
@@ -401,7 +418,8 @@ DESCRIPTION
Only a subset of keywords may be used on the lines following a
Match keyword. Available keywords are AllowAgentForwarding,
- AllowTcpForwarding, AuthorizedKeysFile, AuthorizedPrincipalsFile,
+ AllowTcpForwarding, AuthorizedKeysFile, AuthorizedKeysCommand,
+ AuthorizedKeysCommandRunAs, AuthorizedPrincipalsFile,
Banner, ChrootDirectory, ForceCommand, GatewayPorts,
GSSAPIAuthentication, HostbasedAuthentication,
HostbasedUsesNameFromPacketOnly, KbdInteractiveAuthentication,
diff -up openssh-5.9p0/sshd_config.5.akc openssh-5.9p0/sshd_config.5
--- openssh-5.9p0/sshd_config.5.akc 2011-09-05 14:26:08.750503994 +0200
+++ openssh-5.9p0/sshd_config.5 2011-09-05 14:26:21.987502513 +0200
@@ -706,6 +706,8 @@ Available keywords are
.Cm AllowAgentForwarding ,
.Cm AllowTcpForwarding ,
.Cm AuthorizedKeysFile ,
+.Cm AuthorizedKeysCommand ,
+.Cm AuthorizedKeysCommandRunAs ,
.Cm AuthorizedPrincipalsFile ,
.Cm Banner ,
.Cm ChrootDirectory ,
@@ -718,6 +720,7 @@ Available keywords are
.Cm KerberosAuthentication ,
.Cm MaxAuthTries ,
.Cm MaxSessions ,
+.Cm PubkeyAuthentication ,
.Cm PasswordAuthentication ,
.Cm PermitEmptyPasswords ,
.Cm PermitOpen ,
@@ -926,6 +929,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.9p0/sshd_config.akc openssh-5.9p0/sshd_config
--- openssh-5.9p0/sshd_config.akc 2011-09-05 14:26:08.000000000 +0200
+++ openssh-5.9p0/sshd_config 2011-09-05 14:45:21.135479100 +0200
@@ -49,6 +49,9 @@
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile .ssh/authorized_keys
+#AuthorizedKeysCommand none
+#AuthorizedKeysCommandRunAs nobody
+
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#RhostsRSAAuthentication no
# similar for protocol version 2

641
openssh-5.9p1-audit1.patch Normal file
View File

@ -0,0 +1,641 @@
diff -up openssh-5.9p0/audit-bsm.c.audit1 openssh-5.9p0/audit-bsm.c
--- openssh-5.9p0/audit-bsm.c.audit1 2011-01-17 11:15:29.000000000 +0100
+++ openssh-5.9p0/audit-bsm.c 2011-08-30 10:46:57.704148875 +0200
@@ -298,10 +298,23 @@ audit_connection_from(const char *host,
#endif
}
-void
+int
audit_run_command(const char *command)
{
/* not implemented */
+ return 0;
+}
+
+void
+audit_end_command(int handle, const char *command)
+{
+ /* not implemented */
+}
+
+void
+audit_count_session_open(void)
+{
+ /* not necessary */
}
void
diff -up openssh-5.9p0/audit-linux.c.audit1 openssh-5.9p0/audit-linux.c
--- openssh-5.9p0/audit-linux.c.audit1 2011-01-17 11:15:30.000000000 +0100
+++ openssh-5.9p0/audit-linux.c 2011-08-30 10:46:58.059024733 +0200
@@ -35,13 +35,20 @@
#include "log.h"
#include "audit.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+#include "servconf.h"
#include "canohost.h"
+extern ServerOptions options;
+extern Authctxt *the_authctxt;
+extern u_int utmp_len;
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)
+static void
+linux_audit_user_logxxx(int uid, const char *username,
+ const char *hostname, const char *ip, const char *ttyn, int success, int event)
{
int audit_fd, rc, saved_errno;
@@ -49,11 +56,11 @@ linux_audit_record_event(int uid, const
if (audit_fd < 0) {
if (errno == EINVAL || errno == EPROTONOSUPPORT ||
errno == EAFNOSUPPORT)
- return 1; /* No audit support in kernel */
+ return; /* No audit support in kernel */
else
- return 0; /* Must prevent login */
+ goto fatal_report; /* Must prevent login */
}
- rc = audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN,
+ rc = audit_log_acct_message(audit_fd, event,
NULL, "login", username ? username : "(unknown)",
username == NULL ? uid : -1, hostname, ip, ttyn, success);
saved_errno = errno;
@@ -65,35 +72,119 @@ linux_audit_record_event(int uid, const
if ((rc == -EPERM) && (geteuid() != 0))
rc = 0;
errno = saved_errno;
- return (rc >= 0);
+ if (rc < 0) {
+fatal_report:
+ fatal("linux_audit_write_entry failed: %s", strerror(errno));
+ }
+}
+
+static void
+linux_audit_user_auth(int uid, const char *username,
+ const char *hostname, const char *ip, const char *ttyn, int success, int event)
+{
+ int audit_fd, rc, saved_errno;
+ static const char *event_name[] = {
+ "maxtries exceeded",
+ "root denied",
+ "success",
+ "none",
+ "password",
+ "challenge-response",
+ "pubkey",
+ "hostbased",
+ "gssapi",
+ "invalid user",
+ "nologin",
+ "connection closed",
+ "connection abandoned",
+ "unknown"
+ };
+
+ audit_fd = audit_open();
+ if (audit_fd < 0) {
+ if (errno == EINVAL || errno == EPROTONOSUPPORT ||
+ errno == EAFNOSUPPORT)
+ return; /* No audit support in kernel */
+ else
+ goto fatal_report; /* Must prevent login */
+ }
+
+ if ((event < 0) || (event > SSH_AUDIT_UNKNOWN))
+ event = SSH_AUDIT_UNKNOWN;
+
+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH,
+ NULL, event_name[event], username ? username : "(unknown)",
+ username == NULL ? uid : -1, hostname, ip, ttyn, success);
+ saved_errno = errno;
+ close(audit_fd);
+ /*
+ * Do not report error if the error is EPERM and sshd is run as non
+ * root user.
+ */
+ if ((rc == -EPERM) && (geteuid() != 0))
+ rc = 0;
+ errno = saved_errno;
+ if (rc < 0) {
+fatal_report:
+ fatal("linux_audit_write_entry failed: %s", strerror(errno));
+ }
}
+static int user_login_count = 0;
+
/* Below is the sshd audit API code */
void
audit_connection_from(const char *host, int port)
{
-}
/* not implemented */
+}
-void
+int
audit_run_command(const char *command)
{
- /* not implemented */
+ if (!user_login_count++)
+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
+ NULL, "ssh", 1, AUDIT_USER_LOGIN);
+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
+ NULL, "ssh", 1, AUDIT_USER_START);
+ return 0;
+}
+
+void
+audit_end_command(int handle, const char *command)
+{
+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
+ NULL, "ssh", 1, AUDIT_USER_END);
+ if (user_login_count && !--user_login_count)
+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
+ NULL, "ssh", 1, AUDIT_USER_LOGOUT);
+}
+
+void
+audit_count_session_open(void)
+{
+ user_login_count++;
}
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));
+ if (!user_login_count++)
+ linux_audit_user_logxxx(li->uid, NULL, li->hostname,
+ NULL, li->line, 1, AUDIT_USER_LOGIN);
+ linux_audit_user_logxxx(li->uid, NULL, li->hostname,
+ NULL, li->line, 1, AUDIT_USER_START);
}
void
audit_session_close(struct logininfo *li)
{
- /* not implemented */
+ linux_audit_user_logxxx(li->uid, NULL, li->hostname,
+ NULL, li->line, 1, AUDIT_USER_END);
+ if (user_login_count && !--user_login_count)
+ linux_audit_user_logxxx(li->uid, NULL, li->hostname,
+ NULL, li->line, 1, AUDIT_USER_LOGOUT);
}
void
@@ -101,21 +192,43 @@ audit_event(ssh_audit_event_t event)
{
switch(event) {
case SSH_AUTH_SUCCESS:
- case SSH_CONNECTION_CLOSE:
+ linux_audit_user_auth(-1, audit_username(), NULL,
+ get_remote_ipaddr(), "ssh", 1, event);
+ break;
+
case SSH_NOLOGIN:
- case SSH_LOGIN_EXCEED_MAXTRIES:
case SSH_LOGIN_ROOT_DENIED:
+ linux_audit_user_auth(-1, audit_username(), NULL,
+ get_remote_ipaddr(), "ssh", 0, event);
+ linux_audit_user_logxxx(-1, audit_username(), NULL,
+ get_remote_ipaddr(), "ssh", 0, AUDIT_USER_LOGIN);
break;
+ case SSH_LOGIN_EXCEED_MAXTRIES:
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:
+ linux_audit_user_auth(-1, audit_username(), NULL,
+ get_remote_ipaddr(), "ssh", 0, event);
+ break;
+
+ case SSH_CONNECTION_CLOSE:
+ if (user_login_count) {
+ while (user_login_count--)
+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
+ NULL, "ssh", 1, AUDIT_USER_END);
+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, get_remote_name_or_ip(utmp_len, options.use_dns),
+ NULL, "ssh", 1, AUDIT_USER_LOGOUT);
+ }
+ break;
+
+ case SSH_CONNECTION_ABANDON:
case SSH_INVALID_USER:
- linux_audit_record_event(-1, audit_username(), NULL,
- get_remote_ipaddr(), "sshd", 0);
+ linux_audit_user_logxxx(-1, audit_username(), NULL,
+ get_remote_ipaddr(), "ssh", 0, AUDIT_USER_LOGIN);
break;
default:
diff -up openssh-5.9p0/audit.c.audit1 openssh-5.9p0/audit.c
--- openssh-5.9p0/audit.c.audit1 2011-01-17 11:15:30.000000000 +0100
+++ openssh-5.9p0/audit.c 2011-08-30 10:46:57.822025769 +0200
@@ -140,6 +140,17 @@ audit_event(ssh_audit_event_t event)
}
/*
+ * Called when a child process has called, or will soon call,
+ * audit_session_open.
+ */
+void
+audit_count_session_open(void)
+{
+ debug("audit count session open euid %d user %s", geteuid(),
+ audit_username());
+}
+
+/*
* Called when a user session is started. Argument is the tty allocated to
* the session, or NULL if no tty was allocated.
*
@@ -174,13 +185,29 @@ audit_session_close(struct logininfo *li
/*
* This will be called when a user runs a non-interactive command. Note that
* it may be called multiple times for a single connection since SSH2 allows
- * multiple sessions within a single connection.
+ * multiple sessions within a single connection. Returns a "handle" for
+ * audit_end_command.
*/
-void
+int
audit_run_command(const char *command)
{
debug("audit run command euid %d user %s command '%.200s'", geteuid(),
audit_username(), command);
+ return 0;
+}
+
+/*
+ * This will be called when the non-interactive command finishes. Note that
+ * it may be called multiple times for a single connection since SSH2 allows
+ * multiple sessions within a single connection. "handle" should come from
+ * the corresponding audit_run_command.
+ */
+void
+audit_end_command(int handle, const char *command)
+{
+ debug("audit end nopty exec euid %d user %s command '%.200s'", geteuid(),
+ audit_username(), command);
}
+
# endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-5.9p0/audit.h.audit1 openssh-5.9p0/audit.h
--- openssh-5.9p0/audit.h.audit1 2011-01-17 11:15:30.000000000 +0100
+++ openssh-5.9p0/audit.h 2011-08-30 10:46:57.952035525 +0200
@@ -49,9 +49,11 @@ typedef enum ssh_audit_event_type ssh_au
void audit_connection_from(const char *, int);
void audit_event(ssh_audit_event_t);
+void audit_count_session_open(void);
void audit_session_open(struct logininfo *);
void audit_session_close(struct logininfo *);
-void audit_run_command(const char *);
+int audit_run_command(const char *);
+void audit_end_command(int, const char *);
ssh_audit_event_t audit_classify_auth(const char *);
#endif /* _SSH_AUDIT_H */
diff -up openssh-5.9p0/monitor.c.audit1 openssh-5.9p0/monitor.c
--- openssh-5.9p0/monitor.c.audit1 2011-08-05 22:15:18.000000000 +0200
+++ openssh-5.9p0/monitor.c 2011-08-30 10:50:47.074038891 +0200
@@ -185,6 +185,7 @@ 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_end_command(int, Buffer *);
#endif
static int monitor_read_log(struct monitor *);
@@ -271,6 +272,7 @@ 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_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command},
#endif
{0, 0, NULL}
};
@@ -313,6 +315,7 @@ 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_END_COMMAND, MON_PERMIT, mm_answer_audit_end_command},
#endif
{0, 0, NULL}
};
@@ -1398,6 +1401,12 @@ mm_session_close(Session *s)
debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd);
session_pty_cleanup2(s);
}
+#ifdef SSH_AUDIT_EVENTS
+ if (s->command != NULL) {
+ debug3("%s: command %d", __func__, s->command_handle);
+ session_end_command2(s);
+ }
+#endif
session_unused(s->self);
}
@@ -1720,11 +1729,44 @@ mm_answer_audit_command(int socket, Buff
{
u_int len;
char *cmd;
+ Session *s;
debug3("%s entering", __func__);
cmd = buffer_get_string(m, &len);
+
/* sanity check command, if so how? */
- audit_run_command(cmd);
+ s = session_new();
+ if (s == NULL)
+ fatal("%s: error allocating a session", __func__);
+ s->command = cmd;
+ s->command_handle = audit_run_command(cmd);
+
+ buffer_clear(m);
+ buffer_put_int(m, s->self);
+
+ mm_request_send(socket, MONITOR_ANS_AUDIT_COMMAND, m);
+
+ return (0);
+}
+
+int
+mm_answer_audit_end_command(int socket, Buffer *m)
+{
+ int handle;
+ u_int len;
+ char *cmd;
+ Session *s;
+
+ debug3("%s entering", __func__);
+ handle = buffer_get_int(m);
+ cmd = buffer_get_string(m, &len);
+
+ s = session_by_id(handle);
+ if (s == NULL || s->ttyfd != -1 || s->command == NULL ||
+ strcmp(s->command, cmd) != 0)
+ fatal("%s: invalid handle", __func__);
+ mm_session_close(s);
+
xfree(cmd);
return (0);
}
diff -up openssh-5.9p0/monitor.h.audit1 openssh-5.9p0/monitor.h
--- openssh-5.9p0/monitor.h.audit1 2011-06-20 06:42:23.000000000 +0200
+++ openssh-5.9p0/monitor.h 2011-08-30 10:46:58.392112520 +0200
@@ -60,6 +60,7 @@ enum monitor_reqtype {
MONITOR_REQ_PAM_RESPOND, MONITOR_ANS_PAM_RESPOND,
MONITOR_REQ_PAM_FREE_CTX, MONITOR_ANS_PAM_FREE_CTX,
MONITOR_REQ_AUDIT_EVENT, MONITOR_REQ_AUDIT_COMMAND,
+ MONITOR_ANS_AUDIT_COMMAND, MONITOR_REQ_AUDIT_END_COMMAND,
MONITOR_REQ_TERM,
MONITOR_REQ_JPAKE_STEP1, MONITOR_ANS_JPAKE_STEP1,
MONITOR_REQ_JPAKE_GET_PWDATA, MONITOR_ANS_JPAKE_GET_PWDATA,
diff -up openssh-5.9p0/monitor_wrap.c.audit1 openssh-5.9p0/monitor_wrap.c
--- openssh-5.9p0/monitor_wrap.c.audit1 2011-06-20 06:42:23.000000000 +0200
+++ openssh-5.9p0/monitor_wrap.c 2011-08-30 10:46:58.505031574 +0200
@@ -1188,10 +1188,11 @@ mm_audit_event(ssh_audit_event_t event)
buffer_free(&m);
}
-void
+int
mm_audit_run_command(const char *command)
{
Buffer m;
+ int handle;
debug3("%s entering command %s", __func__, command);
@@ -1199,6 +1200,26 @@ mm_audit_run_command(const char *command
buffer_put_cstring(&m, command);
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, &m);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_COMMAND, &m);
+
+ handle = buffer_get_int(&m);
+ buffer_free(&m);
+
+ return (handle);
+}
+
+void
+mm_audit_end_command(int handle, const char *command)
+{
+ Buffer m;
+
+ debug3("%s entering command %s", __func__, command);
+
+ buffer_init(&m);
+ buffer_put_int(&m, handle);
+ buffer_put_cstring(&m, command);
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_END_COMMAND, &m);
buffer_free(&m);
}
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-5.9p0/monitor_wrap.h.audit1 openssh-5.9p0/monitor_wrap.h
--- openssh-5.9p0/monitor_wrap.h.audit1 2011-06-20 06:42:23.000000000 +0200
+++ openssh-5.9p0/monitor_wrap.h 2011-08-30 10:46:58.616212835 +0200
@@ -74,7 +74,8 @@ void mm_sshpam_free_ctx(void *);
#ifdef SSH_AUDIT_EVENTS
#include "audit.h"
void mm_audit_event(ssh_audit_event_t);
-void mm_audit_run_command(const char *);
+int mm_audit_run_command(const char *);
+void mm_audit_end_command(int, const char *);
#endif
struct Session;
diff -up openssh-5.9p0/session.c.audit1 openssh-5.9p0/session.c
--- openssh-5.9p0/session.c.audit1 2011-05-20 03:23:10.000000000 +0200
+++ openssh-5.9p0/session.c 2011-08-30 10:46:58.756024849 +0200
@@ -742,6 +742,14 @@ do_exec_pty(Session *s, const char *comm
/* Parent. Close the slave side of the pseudo tty. */
close(ttyfd);
+#ifndef HAVE_OSF_SIA
+ /* do_login in the child did not affect state in this process,
+ compensate. From an architectural standpoint, this is extremely
+ ugly. */
+ if (!(options.use_login && command == NULL))
+ audit_count_session_open();
+#endif
+
/* Enter interactive session. */
s->ptymaster = ptymaster;
packet_set_interactive(1,
@@ -813,15 +821,19 @@ do_exec(Session *s, const char *command)
}
#ifdef SSH_AUDIT_EVENTS
+ if (s->command != NULL || s->command_handle != -1)
+ fatal("do_exec: command already set");
if (command != NULL)
- PRIVSEP(audit_run_command(command));
+ s->command = xstrdup(command);
else if (s->ttyfd == -1) {
char *shell = s->pw->pw_shell;
if (shell[0] == '\0') /* empty shell means /bin/sh */
shell =_PATH_BSHELL;
- PRIVSEP(audit_run_command(shell));
+ s->command = xstrdup(shell);
}
+ if (s->command != NULL)
+ s->command_handle = PRIVSEP(audit_run_command(s->command));
#endif
if (s->ttyfd != -1)
ret = do_exec_pty(s, command);
@@ -1848,6 +1860,7 @@ session_unused(int id)
sessions[id].ttyfd = -1;
sessions[id].ptymaster = -1;
sessions[id].x11_chanids = NULL;
+ sessions[id].command_handle = -1;
sessions[id].next_unused = sessions_first_unused;
sessions_first_unused = id;
}
@@ -1930,6 +1943,19 @@ session_open(Authctxt *authctxt, int cha
}
Session *
+session_by_id(int id)
+{
+ if (id >= 0 && id < sessions_nalloc) {
+ Session *s = &sessions[id];
+ if (s->used)
+ return s;
+ }
+ debug("session_by_id: unknown id %d", id);
+ session_dump();
+ return NULL;
+}
+
+Session *
session_by_tty(char *tty)
{
int i;
@@ -2455,6 +2481,30 @@ session_exit_message(Session *s, int sta
chan_write_failed(c);
}
+#ifdef SSH_AUDIT_EVENTS
+void
+session_end_command2(Session *s)
+{
+ if (s->command != NULL) {
+ audit_end_command(s->command_handle, s->command);
+ xfree(s->command);
+ s->command = NULL;
+ s->command_handle = -1;
+ }
+}
+
+static void
+session_end_command(Session *s)
+{
+ if (s->command != NULL) {
+ PRIVSEP(audit_end_command(s->command_handle, s->command));
+ xfree(s->command);
+ s->command = NULL;
+ s->command_handle = -1;
+ }
+}
+#endif
+
void
session_close(Session *s)
{
@@ -2463,6 +2513,10 @@ session_close(Session *s)
debug("session_close: session %d pid %ld", s->self, (long)s->pid);
if (s->ttyfd != -1)
session_pty_cleanup(s);
+#ifdef SSH_AUDIT_EVENTS
+ if (s->command)
+ session_end_command(s);
+#endif
if (s->term)
xfree(s->term);
if (s->display)
@@ -2682,6 +2736,15 @@ do_authenticated2(Authctxt *authctxt)
server_loop2(authctxt);
}
+static void
+do_cleanup_one_session(Session *s)
+{
+ session_pty_cleanup2(s);
+#ifdef SSH_AUDIT_EVENTS
+ session_end_command2(s);
+#endif
+}
+
void
do_cleanup(Authctxt *authctxt)
{
@@ -2730,5 +2793,5 @@ do_cleanup(Authctxt *authctxt)
* or if running in monitor.
*/
if (!use_privsep || mm_is_monitor())
- session_destroy_all(session_pty_cleanup2);
+ session_destroy_all(do_cleanup_one_session);
}
diff -up openssh-5.9p0/session.h.audit1 openssh-5.9p0/session.h
--- openssh-5.9p0/session.h.audit1 2008-05-19 07:34:50.000000000 +0200
+++ openssh-5.9p0/session.h 2011-08-30 10:46:58.884024597 +0200
@@ -60,6 +60,12 @@ struct Session {
char *name;
char *val;
} *env;
+
+ /* exec */
+#ifdef SSH_AUDIT_EVENTS
+ int command_handle;
+ char *command;
+#endif
};
void do_authenticated(Authctxt *);
@@ -72,8 +78,10 @@ void session_close_by_pid(pid_t, int);
void session_close_by_channel(int, void *);
void session_destroy_all(void (*)(Session *));
void session_pty_cleanup2(Session *);
+void session_end_command2(Session *);
Session *session_new(void);
+Session *session_by_id(int);
Session *session_by_tty(char *);
void session_close(Session *);
void do_setusercontext(struct passwd *);
diff -up openssh-5.9p0/sshd.c.audit1 openssh-5.9p0/sshd.c
--- openssh-5.9p0/sshd.c.audit1 2011-06-23 11:45:51.000000000 +0200
+++ openssh-5.9p0/sshd.c 2011-08-30 10:46:59.009025421 +0200
@@ -2364,7 +2364,8 @@ cleanup_exit(int i)
do_cleanup(the_authctxt);
#ifdef SSH_AUDIT_EVENTS
/* done after do_cleanup so it can cancel the PAM auth 'thread' */
- if (!use_privsep || mm_is_monitor())
+ if ((the_authctxt == NULL || !the_authctxt->authenticated) &&
+ (!use_privsep || mm_is_monitor()))
audit_event(SSH_CONNECTION_ABANDON);
#endif
_exit(i);

353
openssh-5.9p1-audit2.patch Normal file
View File

@ -0,0 +1,353 @@
diff -up openssh-5.9p0/audit-bsm.c.audit2 openssh-5.9p0/audit-bsm.c
--- openssh-5.9p0/audit-bsm.c.audit2 2011-08-30 10:55:35.281025258 +0200
+++ openssh-5.9p0/audit-bsm.c 2011-08-30 10:55:37.500052231 +0200
@@ -329,6 +329,12 @@ audit_session_close(struct logininfo *li
/* not implemented */
}
+int
+audit_keyusage(int host_user, const char *type, unsigned bits, char *fp, int rv)
+{
+ /* not implemented */
+}
+
void
audit_event(ssh_audit_event_t event)
{
diff -up openssh-5.9p0/audit-linux.c.audit2 openssh-5.9p0/audit-linux.c
--- openssh-5.9p0/audit-linux.c.audit2 2011-08-30 10:55:35.385102905 +0200
+++ openssh-5.9p0/audit-linux.c 2011-08-30 10:55:38.009088040 +0200
@@ -41,6 +41,8 @@
#include "servconf.h"
#include "canohost.h"
+#define AUDIT_LOG_SIZE 128
+
extern ServerOptions options;
extern Authctxt *the_authctxt;
extern u_int utmp_len;
@@ -130,6 +132,37 @@ fatal_report:
}
}
+int
+audit_keyusage(int host_user, const char *type, unsigned bits, 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 ? "pubkey" : "hostbased", 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%s rport=%d",
+ type, bits, key_fingerprint_prefix(), 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));
+}
+
static int user_login_count = 0;
/* Below is the sshd audit API code */
diff -up openssh-5.9p0/audit.c.audit2 openssh-5.9p0/audit.c
--- openssh-5.9p0/audit.c.audit2 2011-08-30 10:55:35.523141273 +0200
+++ openssh-5.9p0/audit.c 2011-08-30 10:55:37.658024710 +0200
@@ -36,6 +36,7 @@
#include "key.h"
#include "hostfile.h"
#include "auth.h"
+#include "xmalloc.h"
/*
* Care must be taken when using this since it WILL NOT be initialized when
@@ -111,6 +112,22 @@ audit_event_lookup(ssh_audit_event_t ev)
return(event_lookup[i].name);
}
+void
+audit_key(int host_user, int *rv, const Key *key)
+{
+ char *fp;
+ const char *crypto_name;
+
+ fp = key_selected_fingerprint(key, SSH_FP_HEX);
+ if (key->type == KEY_RSA1)
+ crypto_name = "ssh-rsa1";
+ else
+ crypto_name = key_ssh_name(key);
+ if (audit_keyusage(host_user, crypto_name, key_size(key), fp, *rv) == 0)
+ *rv = 0;
+ xfree(fp);
+}
+
# ifndef CUSTOM_SSH_AUDIT_EVENTS
/*
* Null implementations of audit functions.
@@ -209,5 +226,17 @@ audit_end_command(int handle, const char
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 bits, char *fp, int rv)
+{
+ debug("audit %s key usage euid %d user %s key type %s key length %d fingerprint %s%s, result %d",
+ host_user ? "pubkey" : "hostbased", geteuid(), audit_username(), type, bits,
+ key_fingerprint_prefix(), fp, rv);
+}
# endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-5.9p0/audit.h.audit2 openssh-5.9p0/audit.h
--- openssh-5.9p0/audit.h.audit2 2011-08-30 10:55:35.723122290 +0200
+++ openssh-5.9p0/audit.h 2011-08-30 10:55:37.905212176 +0200
@@ -28,6 +28,7 @@
# define _SSH_AUDIT_H
#include "loginrec.h"
+#include "key.h"
enum ssh_audit_event_type {
SSH_LOGIN_EXCEED_MAXTRIES,
@@ -55,5 +56,7 @@ void audit_session_close(struct logininf
int audit_run_command(const char *);
void audit_end_command(int, const char *);
ssh_audit_event_t audit_classify_auth(const char *);
+int audit_keyusage(int, const char *, unsigned, char *, int);
+void audit_key(int, int *, const Key *);
#endif /* _SSH_AUDIT_H */
diff -up openssh-5.9p0/auth-rsa.c.audit2 openssh-5.9p0/auth-rsa.c
--- openssh-5.9p0/auth-rsa.c.audit2 2011-08-30 10:55:33.120097071 +0200
+++ openssh-5.9p0/auth-rsa.c 2011-08-30 10:55:38.729025376 +0200
@@ -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_selected_fingerprint(key, SSH_FP_HEX);
+ if (audit_keyusage(1, "ssh-rsa1", RSA_size(key->rsa) * 8, fp, rv) == 0) {
+ debug("unsuccessful audit");
+ rv = 0;
}
- /* Correct answer. */
- return (1);
+ xfree(fp);
+#endif
+
+ return rv;
}
/*
diff -up openssh-5.9p0/auth.h.audit2 openssh-5.9p0/auth.h
--- openssh-5.9p0/auth.h.audit2 2011-05-29 13:39:38.000000000 +0200
+++ openssh-5.9p0/auth.h 2011-08-30 10:57:43.238087347 +0200
@@ -170,6 +170,7 @@ void abandon_challenge_response(Authctxt
char *expand_authorized_keys(const char *, struct passwd *pw);
char *authorized_principals_file(struct passwd *);
+int user_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 hostbased_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.9p0/auth2-hostbased.c.audit2 openssh-5.9p0/auth2-hostbased.c
--- openssh-5.9p0/auth2-hostbased.c.audit2 2011-08-30 10:55:32.696212587 +0200
+++ openssh-5.9p0/auth2-hostbased.c 2011-08-30 10:55:38.120068864 +0200
@@ -119,7 +119,7 @@ userauth_hostbased(Authctxt *authctxt)
/* test for allowed key and correct signature */
authenticated = 0;
if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
- PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
+ PRIVSEP(hostbased_key_verify(key, sig, slen, buffer_ptr(&b),
buffer_len(&b))) == 1)
authenticated = 1;
@@ -136,6 +136,18 @@ done:
return authenticated;
}
+int
+hostbased_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.9p0/auth2-pubkey.c.audit2 openssh-5.9p0/auth2-pubkey.c
--- openssh-5.9p0/auth2-pubkey.c.audit2 2011-08-30 10:55:32.803126151 +0200
+++ openssh-5.9p0/auth2-pubkey.c 2011-08-30 10:55:38.426108672 +0200
@@ -140,7 +140,7 @@ userauth_pubkey(Authctxt *authctxt)
/* test for correct signature */
authenticated = 0;
if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
- PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
+ PRIVSEP(user_key_verify(key, sig, slen, buffer_ptr(&b),
buffer_len(&b))) == 1)
authenticated = 1;
buffer_free(&b);
@@ -177,6 +177,18 @@ done:
return authenticated;
}
+int
+user_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.9p0/monitor.c.audit2 openssh-5.9p0/monitor.c
--- openssh-5.9p0/monitor.c.audit2 2011-08-30 10:55:35.849023496 +0200
+++ openssh-5.9p0/monitor.c 2011-08-30 10:55:38.848024600 +0200
@@ -1318,9 +1318,11 @@ mm_answer_keyverify(int sock, Buffer *m)
Key *key;
u_char *signature, *data, *blob;
u_int signaturelen, datalen, bloblen;
+ int type = 0;
int verified = 0;
int valid_data = 0;
+ type = buffer_get_int(m);
blob = buffer_get_string(m, &bloblen);
signature = buffer_get_string(m, &signaturelen);
data = buffer_get_string(m, &datalen);
@@ -1328,6 +1330,8 @@ mm_answer_keyverify(int sock, Buffer *m)
if (hostbased_cuser == NULL || hostbased_chost == NULL ||
!monitor_allowed_key(blob, bloblen))
fatal("%s: bad key, not previously allowed", __func__);
+ if (type != key_blobtype)
+ fatal("%s: bad key type", __func__);
key = key_from_blob(blob, bloblen);
if (key == NULL)
@@ -1348,7 +1352,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 = user_key_verify(key, signature, signaturelen, data, datalen);
+ break;
+ case MM_HOSTKEY:
+ verified = hostbased_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 -up openssh-5.9p0/monitor_wrap.c.audit2 openssh-5.9p0/monitor_wrap.c
--- openssh-5.9p0/monitor_wrap.c.audit2 2011-08-30 10:55:36.431043533 +0200
+++ openssh-5.9p0/monitor_wrap.c 2011-08-30 10:55:39.074038187 +0200
@@ -431,7 +431,7 @@ mm_key_allowed(enum mm_keytype type, cha
*/
int
-mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
+mm_key_verify(enum mm_keytype type, Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
{
Buffer m;
u_char *blob;
@@ -445,6 +445,7 @@ mm_key_verify(Key *key, u_char *sig, u_i
return (0);
buffer_init(&m);
+ buffer_put_int(&m, type);
buffer_put_string(&m, blob, len);
buffer_put_string(&m, sig, siglen);
buffer_put_string(&m, data, datalen);
@@ -462,6 +463,19 @@ mm_key_verify(Key *key, u_char *sig, u_i
return (verified);
}
+int
+mm_hostbased_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
+{
+ return mm_key_verify(MM_HOSTKEY, key, sig, siglen, data, datalen);
+}
+
+int
+mm_user_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
+{
+ return mm_key_verify(MM_USERKEY, key, sig, siglen, data, datalen);
+}
+
+
/* Export key state after authentication */
Newkeys *
mm_newkeys_from_blob(u_char *blob, int blen)
diff -up openssh-5.9p0/monitor_wrap.h.audit2 openssh-5.9p0/monitor_wrap.h
--- openssh-5.9p0/monitor_wrap.h.audit2 2011-08-30 10:55:36.550088263 +0200
+++ openssh-5.9p0/monitor_wrap.h 2011-08-30 10:55:39.282151179 +0200
@@ -49,7 +49,8 @@ int mm_key_allowed(enum mm_keytype, char
int mm_user_key_allowed(struct passwd *, Key *);
int mm_hostbased_key_allowed(struct passwd *, char *, char *, Key *);
int mm_auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
-int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int);
+int mm_hostbased_key_verify(Key *, u_char *, u_int, u_char *, u_int);
+int mm_user_key_verify(Key *, u_char *, u_int, u_char *, u_int);
int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *);
BIGNUM *mm_auth_rsa_generate_challenge(Key *);

521
openssh-5.9p1-audit3.patch Normal file
View File

@ -0,0 +1,521 @@
diff -up openssh-5.9p0/Makefile.in.audit3 openssh-5.9p0/Makefile.in
--- openssh-5.9p0/Makefile.in.audit3 2011-08-05 22:15:18.000000000 +0200
+++ openssh-5.9p0/Makefile.in 2011-09-03 19:28:53.226036039 +0200
@@ -71,7 +71,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.9p0/audit-bsm.c.audit3 openssh-5.9p0/audit-bsm.c
--- openssh-5.9p0/audit-bsm.c.audit3 2011-09-03 19:28:51.922034646 +0200
+++ openssh-5.9p0/audit-bsm.c 2011-09-03 19:28:53.475151642 +0200
@@ -396,4 +396,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, pid_t pid, uid_t uid)
+{
+ /* not implemented */
+}
#endif /* BSM */
diff -up openssh-5.9p0/audit-linux.c.audit3 openssh-5.9p0/audit-linux.c
--- openssh-5.9p0/audit-linux.c.audit3 2011-09-03 19:28:52.053030306 +0200
+++ openssh-5.9p0/audit-linux.c 2011-09-03 19:28:53.583026470 +0200
@@ -40,6 +40,8 @@
#include "auth.h"
#include "servconf.h"
#include "canohost.h"
+#include "packet.h"
+#include "cipher.h"
#define AUDIT_LOG_SIZE 128
@@ -269,4 +271,56 @@ 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;
+
+ snprintf(buf, sizeof(buf), "op=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_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION,
+ buf, NULL, get_remote_ipaddr(), NULL, 0);
+ audit_close(audit_fd);
+#endif
+}
+
+void
+audit_kex_body(int ctos, char *enc, char *mac, char *compress, pid_t pid,
+ uid_t uid)
+{
+#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), "op=start direction=%s cipher=%s ksize=%d spid=%jd suid=%jd rport=%d laddr=%s lport=%d ",
+ direction[ctos], enc, cipher ? 8 * cipher->key_len : 0,
+ (intmax_t)pid, (intmax_t)uid,
+ 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_user_message(audit_fd, AUDIT_CRYPTO_SESSION,
+ buf, 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.9p0/audit.c.audit3 openssh-5.9p0/audit.c
--- openssh-5.9p0/audit.c.audit3 2011-09-03 19:28:52.166026259 +0200
+++ openssh-5.9p0/audit.c 2011-09-03 19:28:53.673151432 +0200
@@ -28,6 +28,7 @@
#include <stdarg.h>
#include <string.h>
+#include <unistd.h>
#ifdef SSH_AUDIT_EVENTS
@@ -36,6 +37,8 @@
#include "key.h"
#include "hostfile.h"
#include "auth.h"
+#include "ssh-gss.h"
+#include "monitor_wrap.h"
#include "xmalloc.h"
/*
@@ -128,6 +131,18 @@ audit_key(int host_user, int *rv, const
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, getpid(), getuid()));
+}
+
# ifndef CUSTOM_SSH_AUDIT_EVENTS
/*
* Null implementations of audit functions.
@@ -238,5 +253,26 @@ audit_keyusage(int host_user, const char
host_user ? "pubkey" : "hostbased", geteuid(), audit_username(), type, bits,
key_fingerprint_prefix(), fp, rv);
}
+
+/*
+ * This will be called when the protocol negotiation fails.
+ */
+void
+audit_unsupported_body(int what)
+{
+ debug("audit unsupported protocol euid %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, pid_t pid,
+ uid_t uid)
+{
+ debug("audit protocol negotiation euid %d direction %d cipher %s mac %s compresion %s from pid %ld uid %u",
+ (unsigned)geteuid(), ctos, enc, mac, compress, (long)pid,
+ (unsigned)uid);
+}
# endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-5.9p0/audit.h.audit3 openssh-5.9p0/audit.h
--- openssh-5.9p0/audit.h.audit3 2011-09-03 19:28:52.286024211 +0200
+++ openssh-5.9p0/audit.h 2011-09-03 19:28:53.783027870 +0200
@@ -58,5 +58,9 @@ void audit_end_command(int, const char
ssh_audit_event_t audit_classify_auth(const char *);
int audit_keyusage(int, const char *, unsigned, char *, int);
void 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 *, pid_t, uid_t);
#endif /* _SSH_AUDIT_H */
diff -up openssh-5.9p0/auditstub.c.audit3 openssh-5.9p0/auditstub.c
--- openssh-5.9p0/auditstub.c.audit3 2011-09-03 19:28:53.879026270 +0200
+++ openssh-5.9p0/auditstub.c 2011-09-03 19:28:53.882025491 +0200
@@ -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 <jchadima@redhat.com>
+ */
+
+void
+audit_unsupported(int n)
+{
+}
+
+void
+audit_kex(int ctos, char *enc, char *mac, char *comp)
+{
+}
+
diff -up openssh-5.9p0/cipher.c.audit3 openssh-5.9p0/cipher.c
--- openssh-5.9p0/cipher.c.audit3 2011-08-30 10:34:01.000000000 +0200
+++ openssh-5.9p0/cipher.c 2011-09-03 19:28:53.966162869 +0200
@@ -60,15 +60,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.9p0/cipher.h.audit3 openssh-5.9p0/cipher.h
--- openssh-5.9p0/cipher.h.audit3 2009-01-28 06:38:41.000000000 +0100
+++ openssh-5.9p0/cipher.h 2011-09-03 19:28:54.068070077 +0200
@@ -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.9p0/kex.c.audit3 openssh-5.9p0/kex.c
--- openssh-5.9p0/kex.c.audit3 2010-09-24 14:11:14.000000000 +0200
+++ openssh-5.9p0/kex.c 2011-09-03 19:28:54.177212272 +0200
@@ -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.9p0/monitor.c.audit3 openssh-5.9p0/monitor.c
--- openssh-5.9p0/monitor.c.audit3 2011-09-03 19:28:52.851088094 +0200
+++ openssh-5.9p0/monitor.c 2011-09-03 19:28:54.298087612 +0200
@@ -97,6 +97,7 @@
#include "ssh2.h"
#include "jpake.h"
#include "roaming.h"
+#include "audit.h"
#ifdef GSSAPI
static Gssctxt *gsscontext = NULL;
@@ -187,6 +188,8 @@ int mm_answer_gss_checkmic(int, Buffer *
int mm_answer_audit_event(int, Buffer *);
int mm_answer_audit_command(int, Buffer *);
int mm_answer_audit_end_command(int, Buffer *);
+int mm_answer_audit_unsupported_body(int, Buffer *);
+int mm_answer_audit_kex_body(int, Buffer *);
#endif
static int monitor_read_log(struct monitor *);
@@ -237,6 +240,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},
@@ -275,6 +280,8 @@ struct mon_table mon_dispatch_postauth20
{MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
{MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command},
{MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_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}
};
@@ -306,6 +313,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}
};
@@ -318,6 +327,8 @@ struct mon_table mon_dispatch_postauth15
{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_END_COMMAND, MON_PERMIT, mm_answer_audit_end_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}
};
@@ -2380,3 +2391,44 @@ 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;
+ pid_t pid;
+ uid_t uid;
+
+ ctos = buffer_get_int(m);
+ cipher = buffer_get_string(m, &len);
+ mac = buffer_get_string(m, &len);
+ compress = buffer_get_string(m, &len);
+ pid = buffer_get_int64(m);
+ uid = buffer_get_int64(m);
+
+ audit_kex_body(ctos, cipher, mac, compress, pid, uid);
+
+ buffer_clear(m);
+
+ mm_request_send(sock, MONITOR_ANS_AUDIT_KEX, m);
+ return 0;
+}
+
+#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-5.9p0/monitor.h.audit3 openssh-5.9p0/monitor.h
--- openssh-5.9p0/monitor.h.audit3 2011-09-03 19:28:51.000000000 +0200
+++ openssh-5.9p0/monitor.h 2011-09-03 19:29:52.565211520 +0200
@@ -61,6 +61,8 @@ enum monitor_reqtype {
MONITOR_REQ_PAM_FREE_CTX, MONITOR_ANS_PAM_FREE_CTX,
MONITOR_REQ_AUDIT_EVENT, MONITOR_REQ_AUDIT_COMMAND,
MONITOR_ANS_AUDIT_COMMAND, MONITOR_REQ_AUDIT_END_COMMAND,
+ MONITOR_REQ_AUDIT_UNSUPPORTED, MONITOR_ANS_AUDIT_UNSUPPORTED,
+ MONITOR_REQ_AUDIT_KEX, MONITOR_ANS_AUDIT_KEX,
MONITOR_REQ_TERM,
MONITOR_REQ_JPAKE_STEP1, MONITOR_ANS_JPAKE_STEP1,
MONITOR_REQ_JPAKE_GET_PWDATA, MONITOR_ANS_JPAKE_GET_PWDATA,
diff -up openssh-5.9p0/monitor_wrap.c.audit3 openssh-5.9p0/monitor_wrap.c
--- openssh-5.9p0/monitor_wrap.c.audit3 2011-09-03 19:28:52.963088596 +0200
+++ openssh-5.9p0/monitor_wrap.c 2011-09-03 19:28:54.602024893 +0200
@@ -1505,3 +1505,41 @@ 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, pid_t pid,
+ uid_t uid)
+{
+ 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);
+ buffer_put_int64(&m, pid);
+ buffer_put_int64(&m, uid);
+
+ 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.9p0/monitor_wrap.h.audit3 openssh-5.9p0/monitor_wrap.h
--- openssh-5.9p0/monitor_wrap.h.audit3 2011-09-03 19:28:53.069087341 +0200
+++ openssh-5.9p0/monitor_wrap.h 2011-09-03 19:28:54.704055439 +0200
@@ -78,6 +78,8 @@ void mm_sshpam_free_ctx(void *);
void mm_audit_event(ssh_audit_event_t);
int mm_audit_run_command(const char *);
void mm_audit_end_command(int, const char *);
+void mm_audit_unsupported_body(int);
+void mm_audit_kex_body(int, char *, char *, char *, pid_t, uid_t);
#endif
struct Session;
diff -up openssh-5.9p0/sshd.c.audit3 openssh-5.9p0/sshd.c
--- openssh-5.9p0/sshd.c.audit3 2011-09-03 19:28:51.758025429 +0200
+++ openssh-5.9p0/sshd.c 2011-09-03 19:28:54.835049403 +0200
@@ -118,6 +118,7 @@
#endif
#include "monitor_wrap.h"
#include "roaming.h"
+#include "audit.h"
#include "ssh-sandbox.h"
#include "version.h"
@@ -2204,6 +2205,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. */

636
openssh-5.9p1-audit4.patch Normal file
View File

@ -0,0 +1,636 @@
diff -up openssh-5.9p0/audit-bsm.c.audit4 openssh-5.9p0/audit-bsm.c
--- openssh-5.9p0/audit-bsm.c.audit4 2011-09-03 19:32:58.053087996 +0200
+++ openssh-5.9p0/audit-bsm.c 2011-09-03 19:32:59.670087560 +0200
@@ -408,4 +408,10 @@ audit_kex_body(int ctos, char *enc, char
{
/* not implemented */
}
+
+void
+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)
+{
+ /* not implemented */
+}
#endif /* BSM */
diff -up openssh-5.9p0/audit-linux.c.audit4 openssh-5.9p0/audit-linux.c
--- openssh-5.9p0/audit-linux.c.audit4 2011-09-03 19:32:58.177086248 +0200
+++ openssh-5.9p0/audit-linux.c 2011-09-03 19:32:59.758096254 +0200
@@ -292,6 +292,8 @@ 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, pid_t pid,
uid_t uid)
@@ -299,7 +301,6 @@ audit_kex_body(int ctos, char *enc, char
#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), "op=start direction=%s cipher=%s ksize=%d spid=%jd suid=%jd rport=%d laddr=%s lport=%d ",
@@ -323,4 +324,30 @@ audit_kex_body(int ctos, char *enc, char
#endif
}
+void
+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)
+{
+ char buf[AUDIT_LOG_SIZE];
+ int audit_fd, audit_ok;
+
+ snprintf(buf, sizeof(buf), "op=destroy kind=session fp=? direction=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ",
+ direction[ctos], (intmax_t)pid, (intmax_t)uid,
+ 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)
+ error("cannot open audit");
+ return;
+ }
+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER,
+ buf, 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.9p0/audit.c.audit4 openssh-5.9p0/audit.c
--- openssh-5.9p0/audit.c.audit4 2011-09-03 19:32:58.292030283 +0200
+++ openssh-5.9p0/audit.c 2011-09-03 19:32:59.882149457 +0200
@@ -143,6 +143,12 @@ audit_kex(int ctos, char *enc, char *mac
PRIVSEP(audit_kex_body(ctos, enc, mac, comp, getpid(), getuid()));
}
+void
+audit_session_key_free(int ctos)
+{
+ PRIVSEP(audit_session_key_free_body(ctos, getpid(), getuid()));
+}
+
# ifndef CUSTOM_SSH_AUDIT_EVENTS
/*
* Null implementations of audit functions.
@@ -274,5 +280,15 @@ audit_kex_body(int ctos, char *enc, char
(unsigned)geteuid(), ctos, enc, mac, compress, (long)pid,
(unsigned)uid);
}
+
+/*
+ * This will be called on succesfull session key discard
+ */
+void
+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)
+{
+ debug("audit session key discard euid %u direction %d from pid %ld uid %u",
+ (unsigned)geteuid(), ctos, (long)pid, (unsigned)uid);
+}
# endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-5.9p0/audit.h.audit4 openssh-5.9p0/audit.h
--- openssh-5.9p0/audit.h.audit4 2011-09-03 19:32:58.389152136 +0200
+++ openssh-5.9p0/audit.h 2011-09-03 19:32:59.990088015 +0200
@@ -62,5 +62,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 *, pid_t, uid_t);
+void audit_session_key_free(int ctos);
+void audit_session_key_free_body(int ctos, pid_t, uid_t);
#endif /* _SSH_AUDIT_H */
diff -up openssh-5.9p0/auditstub.c.audit4 openssh-5.9p0/auditstub.c
--- openssh-5.9p0/auditstub.c.audit4 2011-09-03 19:32:58.485025086 +0200
+++ openssh-5.9p0/auditstub.c 2011-09-03 19:33:00.115087744 +0200
@@ -27,6 +27,8 @@
* Red Hat author: Jan F. Chadima <jchadima@redhat.com>
*/
+#include <sys/types.h>
+
void
audit_unsupported(int n)
{
@@ -37,3 +39,12 @@ audit_kex(int ctos, char *enc, char *mac
{
}
+void
+audit_session_key_free(int ctos)
+{
+}
+
+void
+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)
+{
+}
diff -up openssh-5.9p0/kex.c.audit4 openssh-5.9p0/kex.c
--- openssh-5.9p0/kex.c.audit4 2011-09-03 19:32:58.820024508 +0200
+++ openssh-5.9p0/kex.c 2011-09-03 19:33:00.226087442 +0200
@@ -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.9p0/kex.h.audit4 openssh-5.9p0/kex.h
--- openssh-5.9p0/kex.h.audit4 2010-09-24 14:11:14.000000000 +0200
+++ openssh-5.9p0/kex.h 2011-09-03 19:33:00.342212519 +0200
@@ -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.9p0/mac.c.audit4 openssh-5.9p0/mac.c
--- openssh-5.9p0/mac.c.audit4 2011-08-17 02:29:03.000000000 +0200
+++ openssh-5.9p0/mac.c 2011-09-03 19:33:00.476211919 +0200
@@ -168,6 +168,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.9p0/mac.h.audit4 openssh-5.9p0/mac.h
--- openssh-5.9p0/mac.h.audit4 2007-06-11 06:01:42.000000000 +0200
+++ openssh-5.9p0/mac.h 2011-09-03 19:33:00.604046419 +0200
@@ -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.9p0/monitor.c.audit4 openssh-5.9p0/monitor.c
--- openssh-5.9p0/monitor.c.audit4 2011-09-03 19:32:58.992150893 +0200
+++ openssh-5.9p0/monitor.c 2011-09-03 19:33:00.711212900 +0200
@@ -190,6 +190,7 @@ int mm_answer_audit_command(int, Buffer
int mm_answer_audit_end_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 int monitor_read_log(struct monitor *);
@@ -242,6 +243,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},
@@ -282,6 +284,7 @@ struct mon_table mon_dispatch_postauth20
{MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_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}
};
@@ -315,6 +318,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}
};
@@ -329,6 +333,7 @@ struct mon_table mon_dispatch_postauth15
{MONITOR_REQ_AUDIT_END_COMMAND, MON_PERMIT, mm_answer_audit_end_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}
};
@@ -1927,11 +1932,13 @@ mm_get_keystate(struct monitor *pmonitor
blob = buffer_get_string(&m, &bloblen);
current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen);
+ memset(blob, 0, bloblen);
xfree(blob);
debug3("%s: Waiting for second key", __func__);
blob = buffer_get_string(&m, &bloblen);
current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen);
+ memset(blob, 0, bloblen);
xfree(blob);
/* Now get sequence numbers for the packets */
@@ -1977,6 +1984,16 @@ mm_get_keystate(struct monitor *pmonitor
}
buffer_free(&m);
+
+#ifdef SSH_AUDIT_EVENTS
+ if (compat20) {
+ buffer_init(&m);
+ mm_request_receive_expect(pmonitor->m_sendfd,
+ MONITOR_REQ_AUDIT_SESSION_KEY_FREE, &m);
+ mm_answer_audit_session_key_free_body(pmonitor->m_sendfd, &m);
+ buffer_free(&m);
+ }
+#endif
}
@@ -2431,4 +2448,22 @@ mm_answer_audit_kex_body(int sock, Buffe
return 0;
}
+int
+mm_answer_audit_session_key_free_body(int sock, Buffer *m)
+{
+ int ctos;
+ pid_t pid;
+ uid_t uid;
+
+ ctos = buffer_get_int(m);
+ pid = buffer_get_int64(m);
+ uid = buffer_get_int64(m);
+
+ audit_session_key_free_body(ctos, pid, uid);
+
+ buffer_clear(m);
+
+ mm_request_send(sock, MONITOR_ANS_AUDIT_SESSION_KEY_FREE, m);
+ return 0;
+}
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-5.9p0/monitor.h.audit4 openssh-5.9p0/monitor.h
--- openssh-5.9p0/monitor.h.audit4 2011-09-03 19:32:59.000000000 +0200
+++ openssh-5.9p0/monitor.h 2011-09-03 19:33:38.376071005 +0200
@@ -63,6 +63,7 @@ enum monitor_reqtype {
MONITOR_ANS_AUDIT_COMMAND, MONITOR_REQ_AUDIT_END_COMMAND,
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_TERM,
MONITOR_REQ_JPAKE_STEP1, MONITOR_ANS_JPAKE_STEP1,
MONITOR_REQ_JPAKE_GET_PWDATA, MONITOR_ANS_JPAKE_GET_PWDATA,
diff -up openssh-5.9p0/monitor_wrap.c.audit4 openssh-5.9p0/monitor_wrap.c
--- openssh-5.9p0/monitor_wrap.c.audit4 2011-09-03 19:32:59.246088665 +0200
+++ openssh-5.9p0/monitor_wrap.c 2011-09-03 19:33:01.032042297 +0200
@@ -653,12 +653,14 @@ mm_send_keystate(struct monitor *monitor
fatal("%s: conversion of newkeys failed", __func__);
buffer_put_string(&m, blob, bloblen);
+ memset(blob, 0, bloblen);
xfree(blob);
if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen))
fatal("%s: conversion of newkeys failed", __func__);
buffer_put_string(&m, blob, bloblen);
+ memset(blob, 0, bloblen);
xfree(blob);
packet_get_state(MODE_OUT, &seqnr, &blocks, &packets, &bytes);
@@ -1542,4 +1544,19 @@ mm_audit_kex_body(int ctos, char *cipher
buffer_free(&m);
}
+
+void
+mm_audit_session_key_free_body(int ctos, pid_t pid, uid_t uid)
+{
+ Buffer m;
+
+ buffer_init(&m);
+ buffer_put_int(&m, ctos);
+ buffer_put_int64(&m, pid);
+ buffer_put_int64(&m, uid);
+ 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.9p0/monitor_wrap.h.audit4 openssh-5.9p0/monitor_wrap.h
--- openssh-5.9p0/monitor_wrap.h.audit4 2011-09-03 19:32:59.357086584 +0200
+++ openssh-5.9p0/monitor_wrap.h 2011-09-03 19:33:01.136087512 +0200
@@ -80,6 +80,7 @@ int mm_audit_run_command(const char *);
void mm_audit_end_command(int, const char *);
void mm_audit_unsupported_body(int);
void mm_audit_kex_body(int, char *, char *, char *, pid_t, uid_t);
+void mm_audit_session_key_free_body(int, pid_t, uid_t);
#endif
struct Session;
diff -up openssh-5.9p0/packet.c.audit4 openssh-5.9p0/packet.c
--- openssh-5.9p0/packet.c.audit4 2011-09-03 19:32:53.452116806 +0200
+++ openssh-5.9p0/packet.c 2011-09-03 19:33:01.267128421 +0200
@@ -60,6 +60,7 @@
#include <signal.h>
#include "xmalloc.h"
+#include "audit.h"
#include "buffer.h"
#include "packet.h"
#include "crc32.h"
@@ -472,6 +473,13 @@ packet_get_connection_out(void)
return active_state->connection_out;
}
+static int
+packet_state_has_keys (const struct session_state *state)
+{
+ return state != NULL &&
+ (state->newkeys[MODE_IN] != NULL || state->newkeys[MODE_OUT] != NULL);
+}
+
/* Closes the connection and clears and frees internal data structures. */
void
@@ -480,13 +488,6 @@ packet_close(void)
if (!active_state->initialized)
return;
active_state->initialized = 0;
- if (active_state->connection_in == active_state->connection_out) {
- shutdown(active_state->connection_out, SHUT_RDWR);
- close(active_state->connection_out);
- } else {
- close(active_state->connection_in);
- close(active_state->connection_out);
- }
buffer_free(&active_state->input);
buffer_free(&active_state->output);
buffer_free(&active_state->outgoing_packet);
@@ -495,8 +496,18 @@ packet_close(void)
buffer_free(&active_state->compression_buffer);
buffer_compress_uninit();
}
- cipher_cleanup(&active_state->send_context);
- cipher_cleanup(&active_state->receive_context);
+ if (packet_state_has_keys(active_state)) {
+ cipher_cleanup(&active_state->send_context);
+ cipher_cleanup(&active_state->receive_context);
+ audit_session_key_free(2);
+ }
+ if (active_state->connection_in == active_state->connection_out) {
+ shutdown(active_state->connection_out, SHUT_RDWR);
+ close(active_state->connection_out);
+ } else {
+ close(active_state->connection_in);
+ close(active_state->connection_out);
+ }
}
/* Sets remote side protocol flags. */
@@ -731,6 +742,23 @@ packet_send1(void)
*/
}
+static void
+newkeys_destroy_and_free(Newkeys *newkeys)
+{
+ if (newkeys == NULL)
+ return;
+
+ xfree(newkeys->enc.name);
+
+ mac_clear(&newkeys->mac);
+ xfree(newkeys->mac.name);
+
+ xfree(newkeys->comp.name);
+
+ newkeys_destroy(newkeys);
+ xfree(newkeys);
+}
+
void
set_newkeys(int mode)
{
@@ -756,18 +784,9 @@ 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;
- comp = &active_state->newkeys[mode]->comp;
- mac_clear(mac);
- xfree(enc->name);
- xfree(enc->iv);
- xfree(enc->key);
- xfree(mac->name);
- xfree(mac->key);
- xfree(comp->name);
- xfree(active_state->newkeys[mode]);
+ newkeys_destroy_and_free(active_state->newkeys[mode]);
}
active_state->newkeys[mode] = kex_get_newkeys(mode);
if (active_state->newkeys[mode] == NULL)
@@ -1926,6 +1945,47 @@ 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_and_free(state->newkeys[MODE_IN]);
+ state->newkeys[MODE_IN] = NULL;
+ newkeys_destroy_and_free(state->newkeys[MODE_OUT]);
+ state->newkeys[MODE_OUT] = NULL;
+ mac_destroy(state->packet_discard_mac);
+// TAILQ_HEAD(, packet) outgoing;
+// memset(state, 0, sizeof(state));
+}
+
+void
+packet_destroy_all(int audit_it, int privsep)
+{
+ if (audit_it)
+ audit_it = packet_state_has_keys (active_state) ||
+ packet_state_has_keys (backup_state);
+ packet_destroy_state(active_state);
+ packet_destroy_state(backup_state);
+ if (audit_it) {
+#ifdef SSH_AUDIT_EVENTS
+ if (privsep)
+ audit_session_key_free(2);
+ else
+ audit_session_key_free_body(2, getpid(), getuid());
+#endif
+ }
+}
+
/*
* Save the state for the real connection, and use a separate state when
* resuming a suspended connection.
@@ -1933,18 +1993,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();
}
/*
@@ -1961,9 +2015,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);
@@ -1971,4 +2023,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.9p0/packet.h.audit4 openssh-5.9p0/packet.h
--- openssh-5.9p0/packet.h.audit4 2011-05-15 00:43:13.000000000 +0200
+++ openssh-5.9p0/packet.h 2011-09-03 19:33:01.386087369 +0200
@@ -124,4 +124,5 @@ void packet_restore_state(void);
void *packet_get_input(void);
void *packet_get_output(void);
+void packet_destroy_all(int, int);
#endif /* PACKET_H */
diff -up openssh-5.9p0/session.c.audit4 openssh-5.9p0/session.c
--- openssh-5.9p0/session.c.audit4 2011-09-03 19:32:56.232163211 +0200
+++ openssh-5.9p0/session.c 2011-09-03 19:33:01.516024567 +0200
@@ -1634,6 +1634,9 @@ do_child(Session *s, const char *command
/* remove hostkey from the child's memory */
destroy_sensitive_data();
+ /* Don't audit this - both us and the parent would be talking to the
+ monitor over a single socket, with no synchronization. */
+ packet_destroy_all(0, 1);
/* Force a password change */
if (s->authctxt->force_pwchange) {
diff -up openssh-5.9p0/sshd.c.audit4 openssh-5.9p0/sshd.c
--- openssh-5.9p0/sshd.c.audit4 2011-09-03 19:32:59.481087303 +0200
+++ openssh-5.9p0/sshd.c 2011-09-03 19:33:01.657089865 +0200
@@ -684,6 +684,8 @@ privsep_preauth(Authctxt *authctxt)
}
}
+extern Newkeys *current_keys[];
+
static void
privsep_postauth(Authctxt *authctxt)
{
@@ -708,6 +710,10 @@ privsep_postauth(Authctxt *authctxt)
else if (pmonitor->m_pid != 0) {
verbose("User child is on pid %ld", (long)pmonitor->m_pid);
buffer_clear(&loginmsg);
+ newkeys_destroy(current_keys[MODE_OUT]);
+ newkeys_destroy(current_keys[MODE_IN]);
+ audit_session_key_free_body(2, getpid(), getuid());
+ packet_destroy_all(0, 0);
monitor_child_postauth(pmonitor);
/* NEVERREACHED */
@@ -1996,6 +2002,7 @@ main(int ac, char **av)
*/
if (use_privsep) {
mm_send_keystate(pmonitor);
+ packet_destroy_all(1, 1);
exit(0);
}
@@ -2048,6 +2055,8 @@ main(int ac, char **av)
do_authenticated(authctxt);
/* The connection has been terminated. */
+ packet_destroy_all(1, 1);
+
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",
@@ -2367,6 +2376,7 @@ cleanup_exit(int i)
{
if (the_authctxt)
do_cleanup(the_authctxt);
+ packet_destroy_all(1, is_privsep_child);
#ifdef SSH_AUDIT_EVENTS
/* done after do_cleanup so it can cancel the PAM auth 'thread' */
if ((the_authctxt == NULL || !the_authctxt->authenticated) &&

499
openssh-5.9p1-audit5.patch Normal file
View File

@ -0,0 +1,499 @@
diff -up openssh-5.9p0/audit-bsm.c.audit5 openssh-5.9p0/audit-bsm.c
--- openssh-5.9p0/audit-bsm.c.audit5 2011-09-03 19:36:19.596148796 +0200
+++ openssh-5.9p0/audit-bsm.c 2011-09-03 19:36:22.335036037 +0200
@@ -414,4 +414,22 @@ audit_session_key_free_body(int ctos, pi
{
/* not implemented */
}
+
+void
+audit_destroy_sensitive_data(const char *fp)
+{
+ /* not implemented */
+}
+
+void
+audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)
+{
+ /* not implemented */
+}
+
+void
+audit_generate_ephemeral_server_key(const char *fp)
+{
+ /* not implemented */
+}
#endif /* BSM */
diff -up openssh-5.9p0/audit-linux.c.audit5 openssh-5.9p0/audit-linux.c
--- openssh-5.9p0/audit-linux.c.audit5 2011-09-03 19:36:19.693075842 +0200
+++ openssh-5.9p0/audit-linux.c 2011-09-03 19:36:22.783167781 +0200
@@ -350,4 +350,50 @@ audit_session_key_free_body(int ctos, pi
error("cannot write into audit");
}
+void
+audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)
+{
+ char buf[AUDIT_LOG_SIZE];
+ int audit_fd, audit_ok;
+
+ snprintf(buf, sizeof(buf), "op=destroy kind=server fp=%s direction=? spid=%jd suid=%jd ",
+ fp, (intmax_t)pid, (intmax_t)uid);
+ audit_fd = audit_open();
+ if (audit_fd < 0) {
+ if (errno != EINVAL && errno != EPROTONOSUPPORT &&
+ errno != EAFNOSUPPORT)
+ error("cannot open audit");
+ return;
+ }
+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER,
+ buf, NULL,
+ listening_for_clients() ? 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");
+}
+
+void
+audit_generate_ephemeral_server_key(const char *fp)
+{
+ char buf[AUDIT_LOG_SIZE];
+ int audit_fd, audit_ok;
+
+ snprintf(buf, sizeof(buf), "op=create kind=server fp=%s direction=? ", fp);
+ audit_fd = audit_open();
+ if (audit_fd < 0) {
+ if (errno != EINVAL && errno != EPROTONOSUPPORT &&
+ errno != EAFNOSUPPORT)
+ error("cannot open audit");
+ return;
+ }
+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER,
+ buf, NULL, 0, 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.9p0/audit.c.audit5 openssh-5.9p0/audit.c
--- openssh-5.9p0/audit.c.audit5 2011-09-03 19:36:19.798026930 +0200
+++ openssh-5.9p0/audit.c 2011-09-03 19:36:22.894025519 +0200
@@ -290,5 +290,24 @@ audit_session_key_free_body(int ctos, pi
debug("audit session key discard euid %u direction %d from pid %ld uid %u",
(unsigned)geteuid(), ctos, (long)pid, (unsigned)uid);
}
+
+/*
+ * This will be called on destroy private part of the server key
+ */
+void
+audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)
+{
+ debug("audit destroy sensitive data euid %d fingerprint %s from pid %ld uid %u",
+ geteuid(), fp, (long)pid, (unsigned)uid);
+}
+
+/*
+ * This will be called on generation of the ephemeral server key
+ */
+void
+audit_generate_ephemeral_server_key(const char *)
+{
+ debug("audit create ephemeral server key euid %d fingerprint %s", geteuid(), fp);
+}
# endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-5.9p0/audit.h.audit5 openssh-5.9p0/audit.h
--- openssh-5.9p0/audit.h.audit5 2011-09-03 19:36:20.080151641 +0200
+++ openssh-5.9p0/audit.h 2011-09-03 19:36:23.002024714 +0200
@@ -48,6 +48,8 @@ enum ssh_audit_event_type {
};
typedef enum ssh_audit_event_type ssh_audit_event_t;
+int listening_for_clients(void);
+
void audit_connection_from(const char *, int);
void audit_event(ssh_audit_event_t);
void audit_count_session_open(void);
@@ -64,5 +66,7 @@ void audit_unsupported_body(int);
void audit_kex_body(int, char *, char *, char *, pid_t, uid_t);
void audit_session_key_free(int ctos);
void audit_session_key_free_body(int ctos, pid_t, uid_t);
+void audit_destroy_sensitive_data(const char *, pid_t, uid_t);
+void audit_generate_ephemeral_server_key(const char *);
#endif /* _SSH_AUDIT_H */
diff -up openssh-5.9p0/key.c.audit5 openssh-5.9p0/key.c
--- openssh-5.9p0/key.c.audit5 2011-09-03 19:36:11.788093495 +0200
+++ openssh-5.9p0/key.c 2011-09-03 19:36:23.114023593 +0200
@@ -1797,6 +1797,30 @@ key_demote(const Key *k)
}
int
+key_is_private(const Key *k)
+{
+ switch (k->type) {
+ case KEY_RSA_CERT_V00:
+ case KEY_RSA_CERT:
+ case KEY_RSA1:
+ case KEY_RSA:
+ return k->rsa->d != NULL;
+ case KEY_DSA_CERT_V00:
+ case KEY_DSA_CERT:
+ case KEY_DSA:
+ return k->dsa->priv_key != NULL;
+#ifdef OPENSSL_HAS_ECC
+ case KEY_ECDSA_CERT:
+ case KEY_ECDSA:
+ return EC_KEY_get0_private_key(k->ecdsa) != NULL;
+#endif
+ default:
+ fatal("key_is_private: bad key type %d", k->type);
+ return 1;
+ }
+}
+
+int
key_is_cert(const Key *k)
{
if (k == NULL)
diff -up openssh-5.9p0/key.h.audit5 openssh-5.9p0/key.h
--- openssh-5.9p0/key.h.audit5 2011-09-03 19:36:11.873026290 +0200
+++ openssh-5.9p0/key.h 2011-09-03 19:36:23.209025893 +0200
@@ -109,6 +109,7 @@ Key *key_generate(int, u_int);
Key *key_from_private(const Key *);
int key_type_from_name(char *);
int key_is_cert(const Key *);
+int key_is_private(const Key *k);
int key_type_plain(int);
int key_to_certified(Key *, int);
int key_drop_cert(Key *);
diff -up openssh-5.9p0/monitor.c.audit5 openssh-5.9p0/monitor.c
--- openssh-5.9p0/monitor.c.audit5 2011-09-03 19:36:20.953025745 +0200
+++ openssh-5.9p0/monitor.c 2011-09-03 19:36:23.356034851 +0200
@@ -114,6 +114,8 @@ extern Buffer auth_debug;
extern int auth_debug_init;
extern Buffer loginmsg;
+extern void destroy_sensitive_data(int);
+
/* State exported from the child */
struct {
@@ -191,6 +193,7 @@ int mm_answer_audit_end_command(int, Buf
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 int monitor_read_log(struct monitor *);
@@ -244,6 +247,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},
@@ -285,6 +289,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}
};
@@ -319,6 +324,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}
};
@@ -334,6 +340,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}
};
@@ -1722,6 +1729,8 @@ mm_answer_term(int sock, Buffer *req)
sshpam_cleanup();
#endif
+ destroy_sensitive_data(0);
+
while (waitpid(pmonitor->m_pid, &status, 0) == -1)
if (errno != EINTR)
exit(1);
@@ -2466,4 +2475,24 @@ 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)
+{
+ int len;
+ char *fp;
+ pid_t pid;
+ uid_t uid;
+
+ fp = buffer_get_string(m, &len);
+ pid = buffer_get_int64(m);
+ uid = buffer_get_int64(m);
+
+ audit_destroy_sensitive_data(fp, pid, uid);
+
+ buffer_clear(m);
+
+ mm_request_send(sock, MONITOR_ANS_AUDIT_SERVER_KEY_FREE, m);
+ return 0;
+}
#endif /* SSH_AUDIT_EVENTS */
diff -up openssh-5.9p0/monitor.h.audit5 openssh-5.9p0/monitor.h
--- openssh-5.9p0/monitor.h.audit5 2011-09-03 19:36:21.000000000 +0200
+++ openssh-5.9p0/monitor.h 2011-09-03 19:36:54.529052350 +0200
@@ -64,6 +64,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,
MONITOR_REQ_TERM,
MONITOR_REQ_JPAKE_STEP1, MONITOR_ANS_JPAKE_STEP1,
MONITOR_REQ_JPAKE_GET_PWDATA, MONITOR_ANS_JPAKE_GET_PWDATA,
diff -up openssh-5.9p0/monitor_wrap.c.audit5 openssh-5.9p0/monitor_wrap.c
--- openssh-5.9p0/monitor_wrap.c.audit5 2011-09-03 19:36:21.212025456 +0200
+++ openssh-5.9p0/monitor_wrap.c 2011-09-03 19:36:23.714087175 +0200
@@ -1559,4 +1559,20 @@ mm_audit_session_key_free_body(int ctos,
&m);
buffer_free(&m);
}
+
+void
+mm_audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)
+{
+ Buffer m;
+
+ buffer_init(&m);
+ buffer_put_cstring(&m, fp);
+ buffer_put_int64(&m, pid);
+ buffer_put_int64(&m, uid);
+
+ 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.9p0/monitor_wrap.h.audit5 openssh-5.9p0/monitor_wrap.h
--- openssh-5.9p0/monitor_wrap.h.audit5 2011-09-03 19:36:21.316023957 +0200
+++ openssh-5.9p0/monitor_wrap.h 2011-09-03 19:36:23.814151174 +0200
@@ -81,6 +81,7 @@ void mm_audit_end_command(int, const cha
void mm_audit_unsupported_body(int);
void mm_audit_kex_body(int, char *, char *, char *, pid_t, uid_t);
void mm_audit_session_key_free_body(int, pid_t, uid_t);
+void mm_audit_destroy_sensitive_data(const char *, pid_t, uid_t);
#endif
struct Session;
diff -up openssh-5.9p0/session.c.audit5 openssh-5.9p0/session.c
--- openssh-5.9p0/session.c.audit5 2011-09-03 19:36:22.072087382 +0200
+++ openssh-5.9p0/session.c 2011-09-03 19:36:23.985151473 +0200
@@ -136,7 +136,7 @@ extern int log_stderr;
extern int debug_flag;
extern u_int utmp_len;
extern int startup_pipe;
-extern void destroy_sensitive_data(void);
+extern void destroy_sensitive_data(int);
extern Buffer loginmsg;
/* original command from peer. */
@@ -1633,7 +1633,7 @@ do_child(Session *s, const char *command
int r = 0;
/* remove hostkey from the child's memory */
- destroy_sensitive_data();
+ destroy_sensitive_data(1);
/* Don't audit this - both us and the parent would be talking to the
monitor over a single socket, with no synchronization. */
packet_destroy_all(0, 1);
diff -up openssh-5.9p0/sshd.c.audit5 openssh-5.9p0/sshd.c
--- openssh-5.9p0/sshd.c.audit5 2011-09-03 19:36:22.196087195 +0200
+++ openssh-5.9p0/sshd.c 2011-09-03 19:36:24.126148826 +0200
@@ -254,7 +254,7 @@ Buffer loginmsg;
struct passwd *privsep_pw = NULL;
/* Prototypes for various functions defined later in this file. */
-void destroy_sensitive_data(void);
+void destroy_sensitive_data(int);
void demote_sensitive_data(void);
static void do_ssh1_kex(void);
@@ -273,6 +273,15 @@ close_listen_socks(void)
num_listen_socks = -1;
}
+/*
+ * Is this process listening for clients (i.e. not specific to any specific
+ * client connection?)
+ */
+int listening_for_clients(void)
+{
+ return num_listen_socks > 0;
+}
+
static void
close_startup_pipes(void)
{
@@ -533,22 +542,47 @@ sshd_exchange_identification(int sock_in
}
}
-/* Destroy the host and server keys. They will no longer be needed. */
+/*
+ * Destroy the host and server keys. They will no longer be needed. Careful,
+ * this can be called from cleanup_exit() - i.e. from just about anywhere.
+ */
void
-destroy_sensitive_data(void)
+destroy_sensitive_data(int privsep)
{
int i;
+ pid_t pid;
+ uid_t uid;
if (sensitive_data.server_key) {
key_free(sensitive_data.server_key);
sensitive_data.server_key = NULL;
}
+ pid = getpid();
+ uid = getuid();
for (i = 0; i < options.num_host_key_files; i++) {
if (sensitive_data.host_keys[i]) {
+ char *fp;
+
+ if (key_is_private(sensitive_data.host_keys[i]))
+ fp = key_fingerprint(sensitive_data.host_keys[i],
+ FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5,
+ SSH_FP_HEX);
+ else
+ fp = NULL;
key_free(sensitive_data.host_keys[i]);
sensitive_data.host_keys[i] = NULL;
+ if (fp != NULL) {
+ if (privsep)
+ PRIVSEP(audit_destroy_sensitive_data(fp,
+ pid, uid));
+ else
+ audit_destroy_sensitive_data(fp,
+ pid, uid);
+ xfree(fp);
+ }
}
- if (sensitive_data.host_certificates[i]) {
+ if (sensitive_data.host_certificates
+ && sensitive_data.host_certificates[i]) {
key_free(sensitive_data.host_certificates[i]);
sensitive_data.host_certificates[i] = NULL;
}
@@ -562,6 +596,8 @@ void
demote_sensitive_data(void)
{
Key *tmp;
+ pid_t pid;
+ uid_t uid;
int i;
if (sensitive_data.server_key) {
@@ -570,13 +606,27 @@ demote_sensitive_data(void)
sensitive_data.server_key = tmp;
}
+ pid = getpid();
+ uid = getuid();
for (i = 0; i < options.num_host_key_files; i++) {
if (sensitive_data.host_keys[i]) {
+ char *fp;
+
+ if (key_is_private(sensitive_data.host_keys[i]))
+ fp = key_fingerprint(sensitive_data.host_keys[i],
+ FIPS_mode() ? SSH_FP_SHA1 : SSH_FP_MD5,
+ SSH_FP_HEX);
+ else
+ fp = NULL;
tmp = key_demote(sensitive_data.host_keys[i]);
key_free(sensitive_data.host_keys[i]);
sensitive_data.host_keys[i] = tmp;
if (tmp->type == KEY_RSA1)
sensitive_data.ssh1_host_key = tmp;
+ if (fp != NULL) {
+ audit_destroy_sensitive_data(fp, pid, uid);
+ xfree(fp);
+ }
}
/* Certs do not need demotion */
}
@@ -1143,6 +1193,7 @@ server_accept_loop(int *sock_in, int *so
if (received_sigterm) {
logit("Received signal %d; terminating.",
(int) received_sigterm);
+ destroy_sensitive_data(0);
close_listen_socks();
unlink(options.pid_file);
exit(received_sigterm == SIGTERM ? 0 : 255);
@@ -2045,7 +2096,7 @@ main(int ac, char **av)
privsep_postauth(authctxt);
/* the monitor process [priv] will not return */
if (!compat20)
- destroy_sensitive_data();
+ destroy_sensitive_data(0);
}
packet_set_timeout(options.client_alive_interval,
@@ -2056,6 +2107,7 @@ main(int ac, char **av)
/* The connection has been terminated. */
packet_destroy_all(1, 1);
+ destroy_sensitive_data(1);
packet_get_state(MODE_IN, NULL, NULL, NULL, &ibytes);
packet_get_state(MODE_OUT, NULL, NULL, NULL, &obytes);
@@ -2284,7 +2336,7 @@ do_ssh1_kex(void)
session_id[i] = session_key[i] ^ session_key[i + 16];
}
/* Destroy the private and public keys. No longer. */
- destroy_sensitive_data();
+ destroy_sensitive_data(0);
if (use_privsep)
mm_ssh1_session_id(session_id);
@@ -2374,8 +2426,22 @@ do_ssh2_kex(void)
void
cleanup_exit(int i)
{
+ static int in_cleanup;
+
+ int is_privsep_child;
+
+ /* cleanup_exit can be called at the very least from the privsep
+ wrappers used for auditing. Make sure we don't recurse
+ indefinitely. */
+ if (in_cleanup)
+ _exit(i);
+ in_cleanup = 1;
+
if (the_authctxt)
do_cleanup(the_authctxt);
+ is_privsep_child = use_privsep && pmonitor != NULL && !mm_is_monitor();
+ if (sensitive_data.host_keys != NULL)
+ destroy_sensitive_data(is_privsep_child);
packet_destroy_all(1, is_privsep_child);
#ifdef SSH_AUDIT_EVENTS
/* done after do_cleanup so it can cancel the PAM auth 'thread' */

251
openssh-5.9p1-entropy.patch Normal file
View File

@ -0,0 +1,251 @@
diff -up openssh-5.9p0/entropy.c.entropy openssh-5.9p0/entropy.c
--- openssh-5.9p0/entropy.c.entropy 2011-08-31 13:20:59.660150441 +0200
+++ openssh-5.9p0/entropy.c 2011-08-31 13:21:05.072024970 +0200
@@ -232,6 +232,9 @@ seed_rng(void)
memset(buf, '\0', sizeof(buf));
#endif /* OPENSSL_PRNG_ONLY */
+#ifdef __linux__
+ linux_seed();
+#endif /* __linux__ */
if (RAND_status() != 1)
fatal("PRNG is not seeded");
}
diff -up openssh-5.9p0/openbsd-compat/Makefile.in.entropy openssh-5.9p0/openbsd-compat/Makefile.in
--- openssh-5.9p0/openbsd-compat/Makefile.in.entropy 2011-08-31 13:20:54.000000000 +0200
+++ openssh-5.9p0/openbsd-compat/Makefile.in 2011-08-31 13:44:25.138151565 +0200
@@ -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-linux_part_2.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-linux-prng.o port-solaris.o port-tun.o port-uw.o
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
diff -up openssh-5.9p0/openbsd-compat/port-linux-prng.c.entropy openssh-5.9p0/openbsd-compat/port-linux-prng.c
--- openssh-5.9p0/openbsd-compat/port-linux-prng.c.entropy 2011-08-31 13:21:05.382024083 +0200
+++ openssh-5.9p0/openbsd-compat/port-linux-prng.c 2011-08-31 13:21:05.386024776 +0200
@@ -0,0 +1,59 @@
+/* $Id: port-linux.c,v 1.11.4.2 2011/02/04 00:43:08 djm Exp $ */
+
+/*
+ * Copyright (c) 2011 Jan F. Chadima <jchadima@redhat.com>
+ *
+ * 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 - prng support
+ */
+
+#include "includes.h"
+
+#include <errno.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <openssl/rand.h>
+
+#include "log.h"
+#include "xmalloc.h"
+#include "servconf.h"
+#include "port-linux.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+
+void
+linux_seed(void)
+{
+ int len;
+ char *env = getenv("SSH_USE_STRONG_RNG");
+ char *random = "/dev/random";
+ size_t ienv, randlen = 6;
+
+ if (!env || !strcmp(env, "0"))
+ random = "/dev/urandom";
+ else if ((ienv = atoi(env)) > 6)
+ randlen = ienv;
+
+ errno = 0;
+ if ((len = RAND_load_file(random, randlen)) != randlen) {
+ if (errno)
+ fatal ("cannot read from %s, %s", random, strerror(errno));
+ else
+ fatal ("EOF reading %s", random);
+ }
+}
diff -up openssh-5.9p0/ssh-add.1.entropy openssh-5.9p0/ssh-add.1
--- openssh-5.9p0/ssh-add.1.entropy 2010-11-05 00:20:14.000000000 +0100
+++ openssh-5.9p0/ssh-add.1 2011-08-31 13:21:05.597122030 +0200
@@ -158,6 +158,20 @@ Identifies the path of a
.Ux Ns -domain
socket used to communicate with the agent.
.El
+.It Ev SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 6 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
.Sh FILES
.Bl -tag -width Ds
.It Pa ~/.ssh/identity
diff -up openssh-5.9p0/ssh-agent.1.entropy openssh-5.9p0/ssh-agent.1
--- openssh-5.9p0/ssh-agent.1.entropy 2010-12-01 01:50:35.000000000 +0100
+++ openssh-5.9p0/ssh-agent.1 2011-08-31 13:21:05.735150196 +0200
@@ -198,6 +198,24 @@ sockets used to contain the connection t
These sockets should only be readable by the owner.
The sockets should get automatically removed when the agent exits.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 6 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
diff -up openssh-5.9p0/ssh-keygen.1.entropy openssh-5.9p0/ssh-keygen.1
--- openssh-5.9p0/ssh-keygen.1.entropy 2011-08-31 13:20:59.200212619 +0200
+++ openssh-5.9p0/ssh-keygen.1 2011-08-31 13:21:06.077150115 +0200
@@ -669,6 +669,24 @@ Contains Diffie-Hellman groups used for
The file format is described in
.Xr moduli 5 .
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 6 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-add 1 ,
diff -up openssh-5.9p0/ssh-keysign.8.entropy openssh-5.9p0/ssh-keysign.8
--- openssh-5.9p0/ssh-keysign.8.entropy 2010-08-31 14:41:14.000000000 +0200
+++ openssh-5.9p0/ssh-keysign.8 2011-08-31 13:21:06.207024356 +0200
@@ -78,6 +78,24 @@ must be set-uid root if host-based authe
If these files exist they are assumed to contain public certificate
information corresponding with the private keys above.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 6 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh SEE ALSO
.Xr ssh 1 ,
.Xr ssh-keygen 1 ,
diff -up openssh-5.9p0/ssh.1.entropy openssh-5.9p0/ssh.1
--- openssh-5.9p0/ssh.1.entropy 2011-08-31 13:21:00.835103535 +0200
+++ openssh-5.9p0/ssh.1 2011-08-31 13:21:05.482032754 +0200
@@ -1255,6 +1255,23 @@ For more information, see the
.Cm PermitUserEnvironment
option in
.Xr sshd_config 5 .
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.It Ev SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 6 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh FILES
.Bl -tag -width Ds -compact
.It Pa ~/.rhosts
diff -up openssh-5.9p0/sshd.8.entropy openssh-5.9p0/sshd.8
--- openssh-5.9p0/sshd.8.entropy 2011-08-31 13:21:00.000000000 +0200
+++ openssh-5.9p0/sshd.8 2011-08-31 13:46:27.341025537 +0200
@@ -940,6 +940,24 @@ concurrently for different ports, this c
started last).
The content of this file is not sensitive; it can be world-readable.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds -compact
+.Pp
+.It Pa SSH_USE_STRONG_RNG
+The reseeding of the OpenSSL random generator is usually done from
+.Cm /dev/urandom .
+If the
+.Cm SSH_USE_STRONG_RNG
+environment variable is set to value other than
+.Cm 0
+the OpenSSL random generator is reseeded from
+.Cm /dev/random .
+The number of bytes read is defined by the SSH_USE_STRONG_RNG value.
+Minimum is 6 bytes.
+This setting is not recommended on the computers without the hardware
+random generator because insufficient entropy causes the connection to
+be blocked until enough entropy is available.
+.El
.Sh IPV6
IPv6 address can be used everywhere where IPv4 address. In all entries must be the IPv6 address enclosed in square brackets. Note: The square brackets are metacharacters for the shell and must be escaped in shell.
.Sh SEE ALSO

521
openssh-5.9p1-fips.patch Normal file
View File

@ -0,0 +1,521 @@
diff -up openssh-5.9p0/Makefile.in.fips openssh-5.9p0/Makefile.in
--- openssh-5.9p0/Makefile.in.fips 2011-08-31 13:16:25.548087929 +0200
+++ openssh-5.9p0/Makefile.in 2011-08-31 13:17:42.820212398 +0200
@@ -142,25 +142,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-keycat$(EXEEXT): $(LIBCOMPAT) libssh
$(LD) -o $@ ssh-keycat.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(SSHDLIBS)
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.9p0/authfile.c.fips openssh-5.9p0/authfile.c
--- openssh-5.9p0/authfile.c.fips 2011-08-31 13:16:26.896087056 +0200
+++ openssh-5.9p0/authfile.c 2011-08-31 13:16:28.586211616 +0200
@@ -148,8 +148,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);
@@ -472,8 +478,13 @@ key_parse_private_rsa1(Buffer *blob, con
cp = buffer_append_space(&decrypted, buffer_len(&copy));
/* 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(&copy), buffer_len(&copy));
cipher_cleanup(&ciphercontext);
diff -up openssh-5.9p0/cipher-ctr.c.fips openssh-5.9p0/cipher-ctr.c
--- openssh-5.9p0/cipher-ctr.c.fips 2010-10-07 13:06:42.000000000 +0200
+++ openssh-5.9p0/cipher-ctr.c 2011-08-31 13:16:28.690026009 +0200
@@ -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.9p0/cipher.c.fips openssh-5.9p0/cipher.c
--- openssh-5.9p0/cipher.c.fips 2011-08-31 13:16:14.685087304 +0200
+++ openssh-5.9p0/cipher.c 2011-08-31 13:16:28.815092896 +0200
@@ -40,6 +40,7 @@
#include <sys/types.h>
#include <openssl/md5.h>
+#include <openssl/fips.h>
#include <string.h>
#include <stdarg.h>
@@ -86,6 +87,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
@@ -128,7 +145,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;
@@ -138,7 +155,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;
@@ -182,7 +199,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;
@@ -289,14 +306,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);
@@ -304,6 +322,7 @@ cipher_set_key_string(CipherContext *cc,
memset(digest, 0, sizeof(digest));
memset(&md, 0, sizeof(md));
+ return 0;
}
/*
diff -up openssh-5.9p0/cipher.h.fips openssh-5.9p0/cipher.h
--- openssh-5.9p0/cipher.h.fips 2011-08-31 13:16:14.816212495 +0200
+++ openssh-5.9p0/cipher.h 2011-08-31 13:16:28.939073884 +0200
@@ -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.9p0/key.c.fips openssh-5.9p0/key.c
--- openssh-5.9p0/key.c.fips 2011-08-31 13:16:18.179212858 +0200
+++ openssh-5.9p0/key.c 2011-08-31 13:16:29.069031653 +0200
@@ -40,6 +40,7 @@
#include <sys/types.h>
#include <openssl/evp.h>
+#include <openssl/fips.h>
#include <openbsd-compat/openssl-compat.h>
#include <stdarg.h>
@@ -602,9 +603,13 @@ key_fingerprint_selection(void)
char *env;
if (!rv_defined) {
- env = getenv("SSH_FINGERPRINT_TYPE");
- rv = (env && !strcmp (env, "sha")) ?
- SSH_FP_SHA1 : SSH_FP_MD5;
+ if (FIPS_mode())
+ rv = SSH_FP_SHA1;
+ else {
+ env = getenv("SSH_FINGERPRINT_TYPE");
+ rv = (env && !strcmp (env, "sha")) ?
+ SSH_FP_SHA1 : SSH_FP_MD5;
+ }
rv_defined = 1;
}
return rv;
diff -up openssh-5.9p0/mac.c.fips openssh-5.9p0/mac.c
--- openssh-5.9p0/mac.c.fips 2011-08-31 13:16:16.521087343 +0200
+++ openssh-5.9p0/mac.c 2011-08-31 13:16:29.171039694 +0200
@@ -28,6 +28,7 @@
#include <sys/types.h>
#include <openssl/hmac.h>
+#include <openssl/fips.h>
#include <stdarg.h>
#include <string.h>
@@ -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 },
#ifdef HAVE_EVP_SHA256
@@ -71,9 +72,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) {
@@ -94,6 +101,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.9p0/myproposal.h.fips openssh-5.9p0/myproposal.h
--- openssh-5.9p0/myproposal.h.fips 2011-08-17 02:29:03.000000000 +0200
+++ openssh-5.9p0/myproposal.h 2011-08-31 13:16:29.301087416 +0200
@@ -97,6 +97,12 @@
#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.9p0/openbsd-compat/bsd-arc4random.c.fips openssh-5.9p0/openbsd-compat/bsd-arc4random.c
--- openssh-5.9p0/openbsd-compat/bsd-arc4random.c.fips 2010-03-25 22:52:02.000000000 +0100
+++ openssh-5.9p0/openbsd-compat/bsd-arc4random.c 2011-08-31 13:16:29.741086847 +0200
@@ -37,25 +37,18 @@
#define REKEY_BYTES (1 << 24)
static int rc4_ready = 0;
-static RC4_KEY rc4;
unsigned int
arc4random(void)
{
unsigned int r = 0;
- static int first_time = 1;
+ void *rp = &r;
- if (rc4_ready <= 0) {
- if (first_time)
- seed_rng();
- first_time = 0;
+ if (!rc4_ready) {
arc4random_stir();
}
+ RAND_bytes(rp, sizeof(r));
- RC4(&rc4, sizeof(r), (unsigned char *)&r, (unsigned char *)&r);
-
- rc4_ready -= sizeof(r);
-
return(r);
}
@@ -63,24 +56,11 @@ void
arc4random_stir(void)
{
unsigned char rand_buf[SEED_SIZE];
- int i;
- memset(&rc4, 0, sizeof(rc4));
if (RAND_bytes(rand_buf, sizeof(rand_buf)) <= 0)
fatal("Couldn't obtain random bytes (error %ld)",
ERR_get_error());
- RC4_set_key(&rc4, sizeof(rand_buf), rand_buf);
-
- /*
- * Discard early keystream, as per recommendations in:
- * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
- */
- for(i = 0; i <= 256; i += sizeof(rand_buf))
- RC4(&rc4, sizeof(rand_buf), rand_buf, rand_buf);
-
- memset(rand_buf, 0, sizeof(rand_buf));
-
- rc4_ready = REKEY_BYTES;
+ rc4_ready = 1;
}
#endif /* !HAVE_ARC4RANDOM */
diff -up openssh-5.9p0/ssh.c.fips openssh-5.9p0/ssh.c
--- openssh-5.9p0/ssh.c.fips 2011-08-05 22:18:16.000000000 +0200
+++ openssh-5.9p0/ssh.c 2011-08-31 13:16:29.852212356 +0200
@@ -73,6 +73,8 @@
#include <openssl/evp.h>
#include <openssl/err.h>
+#include <openssl/fips.h>
+#include <fipscheck.h>
#include "openbsd-compat/openssl-compat.h"
#include "openbsd-compat/sys-queue.h"
@@ -253,6 +255,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.");
+ }
#ifndef HAVE_SETPROCTITLE
/* Prepare for later setproctitle emulation */
@@ -329,6 +335,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':
@@ -630,7 +639,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. */
@@ -721,6 +729,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);
@@ -789,6 +801,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.9p0/sshconnect2.c.fips openssh-5.9p0/sshconnect2.c
--- openssh-5.9p0/sshconnect2.c.fips 2011-08-31 13:16:09.532024846 +0200
+++ openssh-5.9p0/sshconnect2.c 2011-08-31 13:16:29.959087217 +0200
@@ -44,6 +44,8 @@
#include <vis.h>
#endif
+#include <openssl/fips.h>
+
#include "openbsd-compat/sys-queue.h"
#include "xmalloc.h"
@@ -170,6 +172,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]);
@@ -185,7 +191,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;
diff -up openssh-5.9p0/sshd.c.fips openssh-5.9p0/sshd.c
--- openssh-5.9p0/sshd.c.fips 2011-08-31 13:16:22.525057137 +0200
+++ openssh-5.9p0/sshd.c 2011-08-31 13:16:30.078212687 +0200
@@ -76,6 +76,8 @@
#include <openssl/bn.h>
#include <openssl/md5.h>
#include <openssl/rand.h>
+#include <openssl/fips.h>
+#include <fipscheck.h>
#include "openbsd-compat/openssl-compat.h"
#ifdef HAVE_SECUREWARE
@@ -1388,6 +1390,11 @@ main(int ac, char **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.");
+ }
+
/* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
saved_argc = ac;
rexec_argc = ac;
@@ -1547,8 +1554,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)
@@ -1666,6 +1671,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;
@@ -1830,6 +1839,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("/");
@@ -2372,6 +2385,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]);
@@ -2381,6 +2397,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] =

2932
openssh-5.9p1-gsskex.patch Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,24 @@
diff -up openssh-5.9p0/ssh.1.ipv6man openssh-5.9p0/ssh.1
--- openssh-5.9p0/ssh.1.ipv6man 2011-08-05 22:17:32.000000000 +0200
+++ openssh-5.9p0/ssh.1 2011-08-31 13:08:34.880024485 +0200
@@ -1400,6 +1400,8 @@ manual page for more information.
.Nm
exits with the exit status of the remote command or with 255
if an error occurred.
+.Sh IPV6
+IPv6 address can be used everywhere where IPv4 address. In all entries must be the IPv6 address enclosed in square brackets. Note: The square brackets are metacharacters for the shell and must be escaped in shell.
.Sh SEE ALSO
.Xr scp 1 ,
.Xr sftp 1 ,
diff -up openssh-5.9p0/sshd.8.ipv6man openssh-5.9p0/sshd.8
--- openssh-5.9p0/sshd.8.ipv6man 2011-08-05 22:17:32.000000000 +0200
+++ openssh-5.9p0/sshd.8 2011-08-31 13:10:34.129039094 +0200
@@ -940,6 +940,8 @@ concurrently for different ports, this c
started last).
The content of this file is not sensitive; it can be world-readable.
.El
+.Sh IPV6
+IPv6 address can be used everywhere where IPv4 address. In all entries must be the IPv6 address enclosed in square brackets. Note: The square brackets are metacharacters for the shell and must be escaped in shell.
.Sh SEE ALSO
.Xr scp 1 ,
.Xr sftp 1 ,

371
openssh-5.9p1-keycat.patch Normal file
View File

@ -0,0 +1,371 @@
diff -up openssh-5.9p0/HOWTO.ssh-keycat.keycat openssh-5.9p0/HOWTO.ssh-keycat
--- openssh-5.9p0/HOWTO.ssh-keycat.keycat 2011-08-31 11:51:49.886087176 +0200
+++ openssh-5.9p0/HOWTO.ssh-keycat 2011-08-31 11:51:49.890087179 +0200
@@ -0,0 +1,12 @@
+The ssh-keycat retrieves the content of the ~/.ssh/authorized_keys
+of an user in any environment. This includes environments with
+polyinstantiation of home directories and SELinux MLS policy enabled.
+
+To use ssh-keycat, set these options in /etc/ssh/sshd_config file:
+ AuthorizedKeysCommand /usr/libexec/openssh/ssh-keycat
+ AuthorizedKeysCommandRunAs root
+
+Do not forget to enable public key authentication:
+ PubkeyAuthentication yes
+
+
diff -up openssh-5.9p0/Makefile.in.keycat openssh-5.9p0/Makefile.in
--- openssh-5.9p0/Makefile.in.keycat 2011-08-31 11:51:48.367122382 +0200
+++ openssh-5.9p0/Makefile.in 2011-08-31 12:03:46.433088864 +0200
@@ -27,6 +27,7 @@ SFTP_SERVER=$(libexecdir)/sftp-server
SSH_KEYSIGN=$(libexecdir)/ssh-keysign
SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper
SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper
+SSH_KEYCAT=$(libexecdir)/ssh-keycat
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
PRIVSEP_PATH=@PRIVSEP_PATH@
SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
@@ -62,7 +63,7 @@ EXEEXT=@EXEEXT@
MANFMT=@MANFMT@
INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT)
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT)
LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
@@ -167,6 +168,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT)
ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o
$(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS)
+ssh-keycat$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keycat.o
+ $(LD) -o $@ ssh-keycat.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(SSHDLIBS)
+
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)
@@ -266,6 +270,7 @@ install-files:
$(INSTALL) -m 0700 $(STRIP_OPT) ssh-ldap-helper $(DESTDIR)$(SSH_LDAP_HELPER) ; \
$(INSTALL) -m 0700 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \
fi
+ $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keycat$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-keycat$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
$(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
$(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
diff -up openssh-5.9p0/auth2-pubkey.c.keycat openssh-5.9p0/auth2-pubkey.c
--- openssh-5.9p0/auth2-pubkey.c.keycat 2011-08-31 11:51:47.066149816 +0200
+++ openssh-5.9p0/auth2-pubkey.c 2011-08-31 11:51:50.143087097 +0200
@@ -579,6 +579,14 @@ user_key_via_command_allowed2(struct pas
close(i);
}
+#ifdef WITH_SELINUX
+ if (ssh_selinux_setup_env_variables() < 0) {
+ error ("failed to copy environment: %s",
+ strerror(errno));
+ _exit(127);
+ }
+#endif
+
execl(options.authorized_keys_command, options.authorized_keys_command, pw->pw_name, NULL);
/* if we got here, it didn't work */
diff -up openssh-5.9p0/openbsd-compat/port-linux.c.keycat openssh-5.9p0/openbsd-compat/port-linux.c
--- openssh-5.9p0/openbsd-compat/port-linux.c.keycat 2011-08-31 11:51:46.275119773 +0200
+++ openssh-5.9p0/openbsd-compat/port-linux.c 2011-08-31 11:51:50.240087963 +0200
@@ -313,7 +313,7 @@ ssh_selinux_getctxbyname(char *pwname,
/* Setup environment variables for pam_selinux */
static int
-ssh_selinux_setup_pam_variables(void)
+ssh_selinux_setup_variables(int(*set_it)(const char *, const char *))
{
const char *reqlvl;
char *role;
@@ -324,16 +324,16 @@ ssh_selinux_setup_pam_variables(void)
ssh_selinux_get_role_level(&role, &reqlvl);
- rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : "");
+ rv = set_it("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 || set_it("SELINUX_LEVEL_REQUESTED", reqlvl ? reqlvl: "");
}
- rv = rv || do_pam_putenv("SELINUX_USE_CURRENT_RANGE", use_current);
+ rv = rv || set_it("SELINUX_USE_CURRENT_RANGE", use_current);
if (role != NULL)
xfree(role);
@@ -341,6 +341,24 @@ ssh_selinux_setup_pam_variables(void)
return rv;
}
+static int
+ssh_selinux_setup_pam_variables(void)
+{
+ return ssh_selinux_setup_variables(do_pam_putenv);
+}
+
+static int
+do_setenv(char *name, char *value)
+{
+ return setenv(name, value, 1);
+}
+
+int
+ssh_selinux_setup_env_variables(void)
+{
+ return ssh_selinux_setup_variables(do_setenv);
+}
+
/* Set the execution context to the default for the specified user */
void
ssh_selinux_setup_exec_context(char *pwname)
diff -up openssh-5.9p0/ssh-keycat.c.keycat openssh-5.9p0/ssh-keycat.c
--- openssh-5.9p0/ssh-keycat.c.keycat 2011-08-31 11:51:50.354136025 +0200
+++ openssh-5.9p0/ssh-keycat.c 2011-08-31 11:51:50.359087309 +0200
@@ -0,0 +1,238 @@
+/*
+ * 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, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``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.
+ */
+
+/*
+ * Copyright (c) 2011 Red Hat, Inc.
+ * Written by Tomas Mraz <tmraz@redhat.com>
+*/
+
+#define _GNU_SOURCE
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <security/pam_appl.h>
+
+#include "uidswap.h"
+#include "misc.h"
+
+#define ERR_USAGE 1
+#define ERR_PAM_START 2
+#define ERR_OPEN_SESSION 3
+#define ERR_CLOSE_SESSION 4
+#define ERR_PAM_END 5
+#define ERR_GETPWNAM 6
+#define ERR_MEMORY 7
+#define ERR_OPEN 8
+#define ERR_FILE_MODE 9
+#define ERR_FDOPEN 10
+#define ERR_STAT 11
+#define ERR_WRITE 12
+#define ERR_PAM_PUTENV 13
+#define BUFLEN 4096
+
+/* Just ignore the messages in the conversation function */
+static int
+dummy_conv(int num_msg, const struct pam_message **msgm,
+ struct pam_response **response, void *appdata_ptr)
+{
+ struct pam_response *rsp;
+
+ (void)msgm;
+ (void)appdata_ptr;
+
+ if (num_msg <= 0)
+ return PAM_CONV_ERR;
+
+ /* Just allocate the array as empty responses */
+ rsp = calloc (num_msg, sizeof (struct pam_response));
+ if (rsp == NULL)
+ return PAM_CONV_ERR;
+
+ *response = rsp;
+ return PAM_SUCCESS;
+}
+
+static struct pam_conv conv = {
+ dummy_conv,
+ NULL
+};
+
+char *
+make_auth_keys_name(const struct passwd *pwd)
+{
+ char *fname;
+
+ if (asprintf(&fname, "%s/.ssh/authorized_keys", pwd->pw_dir) < 0)
+ return NULL;
+
+ return fname;
+}
+
+int
+dump_keys(const char *user)
+{
+ struct passwd *pwd;
+ int fd = -1;
+ FILE *f = NULL;
+ char *fname = NULL;
+ int rv = 0;
+ char buf[BUFLEN];
+ size_t len;
+ struct stat st;
+
+ if ((pwd = getpwnam(user)) == NULL) {
+ return ERR_GETPWNAM;
+ }
+
+ if ((fname = make_auth_keys_name(pwd)) == NULL) {
+ return ERR_MEMORY;
+ }
+
+ temporarily_use_uid(pwd);
+
+ if ((fd = open(fname, O_RDONLY|O_NONBLOCK|O_NOFOLLOW, 0)) < 0) {
+ rv = ERR_OPEN;
+ goto fail;
+ }
+
+ if (fstat(fd, &st) < 0) {
+ rv = ERR_STAT;
+ goto fail;
+ }
+
+ if (!S_ISREG(st.st_mode) ||
+ (st.st_uid != pwd->pw_uid && st.st_uid != 0)) {
+ rv = ERR_FILE_MODE;
+ goto fail;
+ }
+
+ unset_nonblock(fd);
+
+ if ((f = fdopen(fd, "r")) == NULL) {
+ rv = ERR_FDOPEN;
+ goto fail;
+ }
+
+ fd = -1;
+
+ while ((len = fread(buf, 1, sizeof(buf), f)) > 0) {
+ rv = fwrite(buf, 1, len, stdout) != len ? ERR_WRITE : 0;
+ }
+
+fail:
+ if (fd != -1)
+ close(fd);
+ if (f != NULL)
+ fclose(f);
+ free(fname);
+ restore_uid();
+ return rv;
+}
+
+static const char *env_names[] = { "SELINUX_ROLE_REQUESTED",
+ "SELINUX_LEVEL_REQUESTED",
+ "SELINUX_USE_CURRENT_RANGE"
+};
+
+extern char **environ;
+
+int
+set_pam_environment(pam_handle_t *pamh)
+{
+ int i;
+ size_t j;
+
+ for (j = 0; j < sizeof(env_names)/sizeof(env_names[0]); ++j) {
+ int len = strlen(env_names[j]);
+
+ for (i = 0; environ[i] != NULL; ++i) {
+ if (strncmp(env_names[j], environ[i], len) == 0 &&
+ environ[i][len] == '=') {
+ if (pam_putenv(pamh, environ[i]) != PAM_SUCCESS)
+ return ERR_PAM_PUTENV;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+ pam_handle_t *pamh = NULL;
+ int retval;
+ int ev = 0;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <user-name>\n", argv[0]);
+ return ERR_USAGE;
+ }
+
+ retval = pam_start("ssh-keycat", argv[1], &conv, &pamh);
+ if (retval != PAM_SUCCESS) {
+ return ERR_PAM_START;
+ }
+
+ ev = set_pam_environment(pamh);
+ if (ev != 0)
+ goto finish;
+
+ retval = pam_open_session(pamh, PAM_SILENT);
+ if (retval != PAM_SUCCESS) {
+ ev = ERR_OPEN_SESSION;
+ goto finish;
+ }
+
+ ev = dump_keys(argv[1]);
+
+ retval = pam_close_session(pamh, PAM_SILENT);
+ if (retval != PAM_SUCCESS) {
+ ev = ERR_CLOSE_SESSION;
+ }
+
+finish:
+ retval = pam_end (pamh,retval);
+ if (retval != PAM_SUCCESS) {
+ ev = ERR_PAM_END;
+ }
+ return ev;
+}

View File

@ -0,0 +1,80 @@
diff -up openssh-5.9p0/ssh-keygen.0.keygen openssh-5.9p0/ssh-keygen.0
--- openssh-5.9p0/ssh-keygen.0.keygen 2011-08-29 16:30:02.000000000 +0200
+++ openssh-5.9p0/ssh-keygen.0 2011-08-30 13:47:56.208087184 +0200
@@ -4,7 +4,7 @@ NAME
ssh-keygen - authentication key generation, management and conversion
SYNOPSIS
- ssh-keygen [-q] [-b bits] -t type [-N new_passphrase] [-C comment]
+ ssh-keygen [-q] [-o] [-b bits] -t type [-N new_passphrase] [-C comment]
[-f output_keyfile]
ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]
ssh-keygen -i [-m key_format] [-f input_keyfile]
@@ -181,6 +181,8 @@ DESCRIPTION
principals may be specified, separated by commas. Please see the
CERTIFICATES section for details.
+ -o Overwrite the key without prompting user.
+
-O option
Specify a certificate option when signing a key. This option may
be specified multiple times. Please see the CERTIFICATES section
diff -up openssh-5.9p0/ssh-keygen.1.keygen openssh-5.9p0/ssh-keygen.1
--- openssh-5.9p0/ssh-keygen.1.keygen 2011-08-30 13:32:30.787149917 +0200
+++ openssh-5.9p0/ssh-keygen.1 2011-08-30 13:46:42.638087171 +0200
@@ -45,6 +45,7 @@
.Bk -words
.Nm ssh-keygen
.Op Fl q
+.Op Fl o
.Op Fl b Ar bits
.Fl t Ar type
.Op Fl N Ar new_passphrase
@@ -339,6 +340,8 @@ Multiple principals may be specified, se
Please see the
.Sx CERTIFICATES
section for details.
+.It Fl o
+Overwrite the key without prompting user.
.It Fl O Ar option
Specify a certificate option when signing a key.
This option may be specified multiple times.
diff -up openssh-5.9p0/ssh-keygen.c.keygen openssh-5.9p0/ssh-keygen.c
--- openssh-5.9p0/ssh-keygen.c.keygen 2011-08-30 13:32:20.268149992 +0200
+++ openssh-5.9p0/ssh-keygen.c 2011-08-30 13:39:34.550214102 +0200
@@ -73,6 +73,7 @@ int change_passphrase = 0;
int change_comment = 0;
int quiet = 0;
+int overwrite = 0;
int log_level = SYSLOG_LEVEL_INFO;
@@ -1959,7 +1960,7 @@ main(int argc, char **argv)
exit(1);
}
- while ((opt = getopt(argc, argv, "AegiqpclBHLhvxXyF:b:f:t:D:I:P:m:N:n:"
+ while ((opt = getopt(argc, argv, "AegiqopclBHLhvxXyF:b:f:t:D:I:P:m:N:n:"
"O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) {
switch (opt) {
case 'A':
@@ -2042,6 +2043,9 @@ main(int argc, char **argv)
case 'q':
quiet = 1;
break;
+ case 'o':
+ overwrite = 1;
+ break;
case 'e':
case 'x':
/* export key */
@@ -2278,7 +2282,7 @@ main(int argc, char **argv)
}
}
/* If the file already exists, ask the user to confirm. */
- if (stat(identity_file, &st) >= 0) {
+ if (!overwrite && stat(identity_file, &st) >= 0) {
char yesno[3];
printf("%s already exists.\n", identity_file);
printf("Overwrite (y/n)? ");

167
openssh-5.9p1-kuserok.patch Normal file
View File

@ -0,0 +1,167 @@
diff -up openssh-5.9p0/auth-krb5.c.kuserok openssh-5.9p0/auth-krb5.c
--- openssh-5.9p0/auth-krb5.c.kuserok 2011-08-30 16:37:32.651150128 +0200
+++ openssh-5.9p0/auth-krb5.c 2011-08-30 16:37:37.549087368 +0200
@@ -54,6 +54,20 @@
extern ServerOptions options;
+int
+ssh_krb5_kuserok(krb5_context krb5_ctx, krb5_principal krb5_user, const char *client)
+{
+ if (options.use_kuserok)
+ return krb5_kuserok(krb5_ctx, krb5_user, client);
+ else {
+ char kuser[65];
+
+ if (krb5_aname_to_localname(krb5_ctx, krb5_user, sizeof(kuser), kuser))
+ return 0;
+ return strcmp(kuser, client) == 0;
+ }
+}
+
static int
krb5_init(void *context)
{
@@ -146,7 +160,7 @@ auth_krb5_password(Authctxt *authctxt, c
if (problem)
goto out;
- if (!krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) {
+ if (!ssh_krb5_kuserok(authctxt->krb5_ctx, authctxt->krb5_user, client)) {
problem = -1;
goto out;
}
diff -up openssh-5.9p0/gss-serv-krb5.c.kuserok openssh-5.9p0/gss-serv-krb5.c
--- openssh-5.9p0/gss-serv-krb5.c.kuserok 2011-08-30 16:37:36.988024804 +0200
+++ openssh-5.9p0/gss-serv-krb5.c 2011-08-30 16:37:37.659088030 +0200
@@ -68,6 +68,7 @@ static int ssh_gssapi_krb5_cmdok(krb5_pr
int);
static krb5_context krb_context = NULL;
+extern int ssh_krb5_kuserok(krb5_context, krb5_principal, const char *);
/* Initialise the krb5 library, for the stuff that GSSAPI won't do */
@@ -115,7 +116,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client
/* NOTE: .k5login and .k5users must opened as root, not the user,
* because if they are on a krb5-protected filesystem, user credentials
* to access these files aren't available yet. */
- if (krb5_kuserok(krb_context, princ, luser) && k5login_exists) {
+ if (ssh_krb5_kuserok(krb_context, princ, luser) && k5login_exists) {
retval = 1;
logit("Authorized to %s, krb5 principal %s (krb5_kuserok)",
luser, (char *)client->displayname.value);
diff -up openssh-5.9p0/servconf.c.kuserok openssh-5.9p0/servconf.c
--- openssh-5.9p0/servconf.c.kuserok 2011-08-30 16:37:35.093073603 +0200
+++ openssh-5.9p0/servconf.c 2011-08-30 16:41:13.568087145 +0200
@@ -144,6 +144,7 @@ initialize_server_options(ServerOptions
options->authorized_principals_file = NULL;
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
+ options->use_kuserok = -1;
}
void
@@ -291,6 +292,8 @@ fill_default_server_options(ServerOption
options->ip_qos_bulk = IPTOS_THROUGHPUT;
if (options->show_patchlevel == -1)
options->show_patchlevel = 0;
+ if (options->use_kuserok == -1)
+ options->use_kuserok = 1;
/* Turn privilege separation on by default */
if (use_privsep == -1)
@@ -317,7 +320,7 @@ typedef enum {
sPermitRootLogin, sLogFacility, sLogLevel,
sRhostsRSAAuthentication, sRSAAuthentication,
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
- sKerberosGetAFSToken,
+ sKerberosGetAFSToken, sKerberosUseKuserok,
sKerberosTgtPassing, sChallengeResponseAuthentication,
sPasswordAuthentication, sKbdInteractiveAuthentication,
sListenAddress, sAddressFamily,
@@ -388,11 +391,13 @@ static struct {
#else
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
#endif
+ { "kerberosusekuserok", sKerberosUseKuserok, SSHCFG_ALL },
#else
{ "kerberosauthentication", sUnsupported, SSHCFG_ALL },
{ "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
{ "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
+ { "kerberosusekuserok", sUnsupported, SSHCFG_ALL },
#endif
{ "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
@@ -1371,6 +1376,10 @@ process_server_config_line(ServerOptions
*activep = value;
break;
+ case sKerberosUseKuserok:
+ intptr = &options->use_kuserok;
+ goto parse_flag;
+
case sPermitOpen:
arg = strdelim(&cp);
if (!arg || *arg == '\0')
@@ -1580,6 +1589,7 @@ copy_set_server_options(ServerOptions *d
M_CP_INTOPT(max_authtries);
M_CP_INTOPT(ip_qos_interactive);
M_CP_INTOPT(ip_qos_bulk);
+ M_CP_INTOPT(use_kuserok);
/* See comment in servconf.h */
COPY_MATCH_STRING_OPTS();
@@ -1816,6 +1826,7 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sUseDNS, o->use_dns);
dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
+ dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok);
/* string arguments */
dump_cfg_string(sPidFile, o->pid_file);
diff -up openssh-5.9p0/servconf.h.kuserok openssh-5.9p0/servconf.h
--- openssh-5.9p0/servconf.h.kuserok 2011-08-30 16:37:35.201051957 +0200
+++ openssh-5.9p0/servconf.h 2011-08-30 16:37:37.926087431 +0200
@@ -166,6 +166,7 @@ typedef struct {
int num_permitted_opens;
+ int use_kuserok;
char *chroot_directory;
char *revoked_keys_file;
char *trusted_user_ca_keys;
diff -up openssh-5.9p0/sshd_config.5.kuserok openssh-5.9p0/sshd_config.5
--- openssh-5.9p0/sshd_config.5.kuserok 2011-08-30 16:37:35.979024607 +0200
+++ openssh-5.9p0/sshd_config.5 2011-08-30 16:37:38.040087843 +0200
@@ -603,6 +603,10 @@ Specifies whether to automatically destr
file on logout.
The default is
.Dq yes .
+.It Cm KerberosUseKuserok
+Specifies whether to look at .k5login file for user's aliases.
+The default is
+.Dq yes .
.It Cm KexAlgorithms
Specifies the available KEX (Key Exchange) algorithms.
Multiple algorithms must be comma-separated.
@@ -746,6 +750,7 @@ Available keywords are
.Cm HostbasedUsesNameFromPacketOnly ,
.Cm KbdInteractiveAuthentication ,
.Cm KerberosAuthentication ,
+.Cm KerberosUseKuserok ,
.Cm MaxAuthTries ,
.Cm MaxSessions ,
.Cm PubkeyAuthentication ,
diff -up openssh-5.9p0/sshd_config.kuserok openssh-5.9p0/sshd_config
--- openssh-5.9p0/sshd_config.kuserok 2011-08-30 16:37:36.808026328 +0200
+++ openssh-5.9p0/sshd_config 2011-08-30 16:37:38.148071520 +0200
@@ -77,6 +77,7 @@ ChallengeResponseAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
+#KerberosUseKuserok yes
# GSSAPI options
#GSSAPIAuthentication no

2596
openssh-5.9p1-ldap.patch Normal file

File diff suppressed because it is too large Load Diff

400
openssh-5.9p1-mls.patch Normal file
View File

@ -0,0 +1,400 @@
diff -up openssh-5.9p0/misc.c.mls openssh-5.9p0/misc.c
--- openssh-5.9p0/misc.c.mls 2011-05-05 06:14:34.000000000 +0200
+++ openssh-5.9p0/misc.c 2011-08-30 12:29:29.157087474 +0200
@@ -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.9p0/openbsd-compat/port-linux.c.mls openssh-5.9p0/openbsd-compat/port-linux.c
--- openssh-5.9p0/openbsd-compat/port-linux.c.mls 2011-08-30 12:29:28.873086987 +0200
+++ openssh-5.9p0/openbsd-compat/port-linux.c 2011-08-30 13:28:12.584149668 +0200
@@ -40,7 +40,15 @@
#ifdef WITH_SELINUX
#include <selinux/selinux.h>
#include <selinux/flask.h>
+#include <selinux/context.h>
#include <selinux/get_context_list.h>
+#include <selinux/get_default_type.h>
+#include <selinux/av_permissions.h>
+
+#ifdef HAVE_LINUX_AUDIT
+#include <libaudit.h>
+#include <unistd.h>
+#endif
#ifndef SSH_SELINUX_UNCONFINED_TYPE
# define SSH_SELINUX_UNCONFINED_TYPE ":unconfined_t:"
@@ -51,6 +59,149 @@ 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)
{
@@ -69,14 +220,15 @@ 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 = NULL;
ssh_selinux_get_role_level(&role, &reqlvl);
@@ -87,37 +239,62 @@ 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
@@ -126,8 +303,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 */
@@ -165,6 +346,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;
@@ -189,22 +372,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__);
}
@@ -222,7 +428,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.9p0/sshd.c.mls openssh-5.9p0/sshd.c
--- openssh-5.9p0/sshd.c.mls 2011-08-30 12:29:22.663149706 +0200
+++ openssh-5.9p0/sshd.c 2011-08-30 12:29:29.524024777 +0200
@@ -2082,6 +2082,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);

View File

@ -0,0 +1,13 @@
diff -up openssh-5.9p0/entropy.c.randclean openssh-5.9p0/entropy.c
--- openssh-5.9p0/entropy.c.randclean 2011-08-30 13:52:45.000000000 +0200
+++ openssh-5.9p0/entropy.c 2011-08-30 13:57:44.630111338 +0200
@@ -217,6 +217,9 @@ seed_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
if (RAND_status() == 1) {
debug3("RNG is ready, skipping seeding");

108
openssh-5.9p1-redhat.patch Normal file
View File

@ -0,0 +1,108 @@
diff -up openssh-5.9p0/ssh_config.redhat openssh-5.9p0/ssh_config
--- openssh-5.9p0/ssh_config.redhat 2010-01-12 09:40:27.000000000 +0100
+++ openssh-5.9p0/ssh_config 2011-09-05 14:48:16.386439023 +0200
@@ -45,3 +45,14 @@
# PermitLocalCommand no
# VisualHostKey no
# ProxyCommand ssh -q -W %h:%p gateway.example.com
+Host *
+ GSSAPIAuthentication yes
+# If this option is set to yes then remote X11 clients will have full access
+# to the original X11 display. As virtually no X11 client supports the untrusted
+# mode correctly we set this to yes.
+ ForwardX11Trusted yes
+# Send locale-related environment variables
+ SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
+ SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
+ SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE
+ SendEnv XMODIFIERS
diff -up openssh-5.9p0/sshd_config.0.redhat openssh-5.9p0/sshd_config.0
--- openssh-5.9p0/sshd_config.0.redhat 2011-09-05 14:48:08.522441255 +0200
+++ openssh-5.9p0/sshd_config.0 2011-09-05 14:48:16.477443868 +0200
@@ -581,9 +581,9 @@ DESCRIPTION
SyslogFacility
Gives the facility code that is used when logging messages from
- sshd(8). The possible values are: DAEMON, USER, AUTH, LOCAL0,
- LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The
- default is AUTH.
+ sshd(8). The possible values are: DAEMON, USER, AUTH, AUTHPRIV,
+ LOCAL0, LOCAL1, LOCAL2, LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
+ The default is AUTH.
TCPKeepAlive
Specifies whether the system should send TCP keepalive messages
diff -up openssh-5.9p0/sshd_config.5.redhat openssh-5.9p0/sshd_config.5
--- openssh-5.9p0/sshd_config.5.redhat 2011-09-05 14:48:08.657564688 +0200
+++ openssh-5.9p0/sshd_config.5 2011-09-05 14:48:16.589501736 +0200
@@ -1029,7 +1029,7 @@ Note that this option applies to protoco
.It Cm SyslogFacility
Gives the facility code that is used when logging messages from
.Xr sshd 8 .
-The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
+The possible values are: DAEMON, USER, AUTH, AUTHPRIV, LOCAL0, LOCAL1, LOCAL2,
LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7.
The default is AUTH.
.It Cm TCPKeepAlive
diff -up openssh-5.9p0/sshd_config.redhat openssh-5.9p0/sshd_config
--- openssh-5.9p0/sshd_config.redhat 2011-09-05 14:48:16.250626793 +0200
+++ openssh-5.9p0/sshd_config 2011-09-05 15:06:01.513443553 +0200
@@ -32,6 +32,7 @@
# Logging
# obsoletes QuietMode and FascistLogging
#SyslogFacility AUTH
+SyslogFacility AUTHPRIV
#LogLevel INFO
# Authentication:
@@ -65,9 +66,11 @@ AuthorizedKeysFile .ssh/authorized_keys
# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
+PasswordAuthentication yes
# Change to no to disable s/key passwords
#ChallengeResponseAuthentication yes
+ChallengeResponseAuthentication no
# Kerberos options
#KerberosAuthentication no
@@ -77,7 +80,9 @@ AuthorizedKeysFile .ssh/authorized_keys
# GSSAPI options
#GSSAPIAuthentication no
+GSSAPIAuthentication yes
#GSSAPICleanupCredentials yes
+GSSAPICleanupCredentials yes
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
@@ -89,6 +94,7 @@ AuthorizedKeysFile .ssh/authorized_keys
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
#UsePAM no
+UsePAM yes
#TwoFactorAuthentication no
#SecondPubkeyAuthentication yes
@@ -101,6 +107,7 @@ AuthorizedKeysFile .ssh/authorized_keys
#AllowTcpForwarding yes
#GatewayPorts no
#X11Forwarding no
+X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PrintMotd yes
@@ -121,6 +128,12 @@ AuthorizedKeysFile .ssh/authorized_keys
# no default banner path
#Banner none
+# Accept locale-related environment variables
+AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
+AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
+AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
+AcceptEnv XMODIFIERS
+
# override default of no subsystems
Subsystem sftp /usr/libexec/sftp-server

613
openssh-5.9p1-role.patch Normal file
View File

@ -0,0 +1,613 @@
diff -up openssh-5.9p0/auth-pam.c.role openssh-5.9p0/auth-pam.c
--- openssh-5.9p0/auth-pam.c.role 2009-07-12 14:07:21.000000000 +0200
+++ openssh-5.9p0/auth-pam.c 2011-08-31 11:42:54.870087433 +0200
@@ -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.9p0/auth-pam.h.role openssh-5.9p0/auth-pam.h
--- openssh-5.9p0/auth-pam.h.role 2004-09-11 14:17:26.000000000 +0200
+++ openssh-5.9p0/auth-pam.h 2011-08-31 11:42:54.979086333 +0200
@@ -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.9p0/auth.h.role openssh-5.9p0/auth.h
--- openssh-5.9p0/auth.h.role 2011-08-31 11:42:47.760024631 +0200
+++ openssh-5.9p0/auth.h 2011-08-31 11:42:55.090151027 +0200
@@ -59,6 +59,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.9p0/auth1.c.role openssh-5.9p0/auth1.c
--- openssh-5.9p0/auth1.c.role 2010-08-31 14:36:39.000000000 +0200
+++ openssh-5.9p0/auth1.c 2011-08-31 11:42:55.215033075 +0200
@@ -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.9p0/auth2-gss.c.role openssh-5.9p0/auth2-gss.c
--- openssh-5.9p0/auth2-gss.c.role 2011-05-05 06:04:11.000000000 +0200
+++ openssh-5.9p0/auth2-gss.c 2011-08-31 11:42:55.313025576 +0200
@@ -260,6 +260,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;
@@ -272,7 +273,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);
@@ -284,6 +291,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.9p0/auth2-hostbased.c.role openssh-5.9p0/auth2-hostbased.c
--- openssh-5.9p0/auth2-hostbased.c.role 2011-08-31 11:42:47.863023264 +0200
+++ openssh-5.9p0/auth2-hostbased.c 2011-08-31 11:42:55.421024814 +0200
@@ -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.9p0/auth2-pubkey.c.role openssh-5.9p0/auth2-pubkey.c
--- openssh-5.9p0/auth2-pubkey.c.role 2011-08-31 11:42:47.978087418 +0200
+++ openssh-5.9p0/auth2-pubkey.c 2011-08-31 11:42:55.551025263 +0200
@@ -121,7 +121,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.9p0/auth2.c.role openssh-5.9p0/auth2.c
--- openssh-5.9p0/auth2.c.role 2011-08-31 11:42:45.409026065 +0200
+++ openssh-5.9p0/auth2.c 2011-08-31 11:42:55.676024869 +0200
@@ -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;
@@ -249,8 +257,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.9p0/monitor.c.role openssh-5.9p0/monitor.c
--- openssh-5.9p0/monitor.c.role 2011-08-31 11:42:53.301024819 +0200
+++ openssh-5.9p0/monitor.c 2011-08-31 11:42:55.796025812 +0200
@@ -148,6 +148,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 *);
@@ -231,6 +234,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
@@ -819,6 +825,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);
}
#ifdef USE_PAM
@@ -862,6 +871,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)
{
@@ -1227,7 +1255,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;
@@ -1253,6 +1281,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);
@@ -1284,7 +1314,7 @@ monitor_valid_hostbasedblob(u_char *data
char *chost)
{
Buffer b;
- char *p;
+ char *p, *r;
u_int len;
int fail = 0;
@@ -1301,6 +1331,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.9p0/monitor.h.role openssh-5.9p0/monitor.h
--- openssh-5.9p0/monitor.h.role 2011-08-31 11:42:53.409025333 +0200
+++ openssh-5.9p0/monitor.h 2011-08-31 11:42:55.889024801 +0200
@@ -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.9p0/monitor_wrap.c.role openssh-5.9p0/monitor_wrap.c
--- openssh-5.9p0/monitor_wrap.c.role 2011-08-31 11:42:53.548024503 +0200
+++ openssh-5.9p0/monitor_wrap.c 2011-08-31 11:42:56.029024553 +0200
@@ -336,6 +336,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.9p0/monitor_wrap.h.role openssh-5.9p0/monitor_wrap.h
--- openssh-5.9p0/monitor_wrap.h.role 2011-08-31 11:42:53.660025271 +0200
+++ openssh-5.9p0/monitor_wrap.h 2011-08-31 11:42:56.131025748 +0200
@@ -42,6 +42,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.9p0/openbsd-compat/Makefile.in.role openssh-5.9p0/openbsd-compat/Makefile.in
--- openssh-5.9p0/openbsd-compat/Makefile.in.role 2010-10-07 13:19:24.000000000 +0200
+++ openssh-5.9p0/openbsd-compat/Makefile.in 2011-08-31 11:48:02.404091479 +0200
@@ -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.9p0/openbsd-compat/port-linux.c.role openssh-5.9p0/openbsd-compat/port-linux.c
--- openssh-5.9p0/openbsd-compat/port-linux.c.role 2011-08-29 08:09:57.000000000 +0200
+++ openssh-5.9p0/openbsd-compat/port-linux.c 2011-08-31 11:42:56.492087969 +0200
@@ -31,7 +31,11 @@
#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 <selinux/selinux.h>
@@ -42,41 +46,63 @@
# define SSH_SELINUX_UNCONFINED_TYPE ":unconfined_t:"
#endif
-/* 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()) {
@@ -104,6 +130,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)
@@ -113,6 +169,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);
@@ -220,21 +294,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.9p0/openbsd-compat/port-linux_part_2.c.role openssh-5.9p0/openbsd-compat/port-linux_part_2.c
--- openssh-5.9p0/openbsd-compat/port-linux_part_2.c.role 2011-08-31 11:42:56.583047619 +0200
+++ openssh-5.9p0/openbsd-compat/port-linux_part_2.c 2011-08-31 11:42:56.586178005 +0200
@@ -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 <dwalsh@redhat.com>
+ * Copyright (c) 2006 Damien Miller <djm@openbsd.org>
+ *
+ * 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 <errno.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "log.h"
+#include "xmalloc.h"
+#include "port-linux.h"
+#include "key.h"
+#include "hostfile.h"
+#include "auth.h"
+
+#ifdef WITH_SELINUX
+#include <selinux/selinux.h>
+#include <selinux/flask.h>
+#include <selinux/get_context_list.h>
+
+/* 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 */

View File

@ -0,0 +1,63 @@
diff -up openssh-5.9p0/openbsd-compat/port-linux.c.sftp-chroot openssh-5.9p0/openbsd-compat/port-linux.c
--- openssh-5.9p0/openbsd-compat/port-linux.c.sftp-chroot 2011-09-01 04:12:22.743024608 +0200
+++ openssh-5.9p0/openbsd-compat/port-linux.c 2011-09-01 04:12:23.069088065 +0200
@@ -503,6 +503,23 @@ ssh_selinux_change_context(const char *n
xfree(newctx);
}
+void
+ssh_selinux_copy_context(void)
+{
+ char *ctx;
+
+ if (!ssh_selinux_enabled())
+ return;
+
+ if (getexeccon((security_context_t *)&ctx) < 0) {
+ logit("%s: getcon failed with %s", __func__, strerror (errno));
+ return;
+ }
+ if (setcon(ctx) < 0)
+ logit("%s: setcon failed with %s", __func__, strerror (errno));
+ xfree(ctx);
+}
+
#endif /* WITH_SELINUX */
#ifdef LINUX_OOM_ADJUST
diff -up openssh-5.9p0/openbsd-compat/port-linux.h.sftp-chroot openssh-5.9p0/openbsd-compat/port-linux.h
--- openssh-5.9p0/openbsd-compat/port-linux.h.sftp-chroot 2011-01-25 02:16:18.000000000 +0100
+++ openssh-5.9p0/openbsd-compat/port-linux.h 2011-09-01 04:12:23.163088777 +0200
@@ -24,6 +24,7 @@ int ssh_selinux_enabled(void);
void ssh_selinux_setup_pty(char *, const char *);
void ssh_selinux_setup_exec_context(char *);
void ssh_selinux_change_context(const char *);
+void ssh_selinux_chopy_context(void);
void ssh_selinux_setfscreatecon(const char *);
#endif
diff -up openssh-5.9p0/session.c.sftp-chroot openssh-5.9p0/session.c
--- openssh-5.9p0/session.c.sftp-chroot 2011-09-01 04:12:19.698049195 +0200
+++ openssh-5.9p0/session.c 2011-09-01 04:40:03.598148719 +0200
@@ -1519,6 +1519,9 @@ do_setusercontext(struct passwd *pw)
pw->pw_uid);
chroot_path = percent_expand(tmp, "h", pw->pw_dir,
"u", pw->pw_name, (char *)NULL);
+#ifdef WITH_SELINUX
+ ssh_selinux_change_context("chroot_user_t");
+#endif
safely_chroot(chroot_path, pw->pw_uid);
free(tmp);
free(chroot_path);
@@ -1788,7 +1791,10 @@ do_child(Session *s, const char *command
optind = optreset = 1;
__progname = argv[0];
#ifdef WITH_SELINUX
- ssh_selinux_change_context("sftpd_t");
+ if (options.chroot_directory == NULL ||
+ strcasecmp(options.chroot_directory, "none") == 0) {
+ ssh_selinux_copy_context();
+ }
#endif
exit(sftp_server_main(i, argv, s->pw));
}

157
openssh-5.9p1-vendor.patch Normal file
View File

@ -0,0 +1,157 @@
diff -up openssh-5.9p0/configure.ac.vendor openssh-5.9p0/configure.ac
--- openssh-5.9p0/configure.ac.vendor 2011-09-03 20:24:29.899501572 +0200
+++ openssh-5.9p0/configure.ac 2011-09-03 20:24:39.153501595 +0200
@@ -4131,6 +4131,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
@@ -4357,6 +4363,7 @@ echo " Translate v4 in v6 hack
echo " BSD Auth support: $BSD_AUTH_MSG"
echo " Random number source: $RAND_MSG"
echo " Privsep sandbox style: $SANDBOX_STYLE"
+echo " Vendor patch level: $SSH_VENDOR_PATCHLEVEL"
echo ""
diff -up openssh-5.9p0/servconf.c.vendor openssh-5.9p0/servconf.c
--- openssh-5.9p0/servconf.c.vendor 2011-09-03 20:24:29.080500853 +0200
+++ openssh-5.9p0/servconf.c 2011-09-03 20:27:15.727564566 +0200
@@ -130,6 +130,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;
@@ -300,6 +301,8 @@ fill_default_server_options(ServerOption
options->ip_qos_interactive = IPTOS_LOWDELAY;
if (options->ip_qos_bulk == -1)
options->ip_qos_bulk = IPTOS_THROUGHPUT;
+ if (options->show_patchlevel == -1)
+ options->show_patchlevel = 0;
/* Turn privilege separation on by default */
if (use_privsep == -1)
@@ -338,7 +341,7 @@ typedef enum {
sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
sMaxStartups, sMaxAuthTries, sMaxSessions,
- sBanner, sUseDNS, sHostbasedAuthentication,
+ sBanner, sShowPatchLevel, sUseDNS, sHostbasedAuthentication,
sHostbasedUsesNameFromPacketOnly, sTwoFactorAuthentication,
sSecondPubkeyAuthentication, sSecondGssAuthentication,
sSecondPasswordAuthentication, sSecondKbdInteractiveAuthentication,
@@ -470,6 +473,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 },
@@ -1152,6 +1156,10 @@ process_server_config_line(ServerOptions
multistate_ptr = multistate_privsep;
goto parse_multistate;
+ case sShowPatchLevel:
+ intptr = &options->show_patchlevel;
+ goto parse_flag;
+
case sAllowUsers:
while ((arg = strdelim(&cp)) && *arg != '\0') {
if (options->num_allow_users >= MAX_ALLOW_USERS)
@@ -1849,6 +1857,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.9p0/servconf.h.vendor openssh-5.9p0/servconf.h
--- openssh-5.9p0/servconf.h.vendor 2011-09-03 20:24:29.179632045 +0200
+++ openssh-5.9p0/servconf.h 2011-09-03 20:24:39.426502323 +0200
@@ -148,6 +148,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.9p0/sshd.c.vendor openssh-5.9p0/sshd.c
--- openssh-5.9p0/sshd.c.vendor 2011-09-03 20:24:35.987501565 +0200
+++ openssh-5.9p0/sshd.c 2011-09-03 20:24:39.542501643 +0200
@@ -431,7 +431,7 @@ sshd_exchange_identification(int sock_in
minor = PROTOCOL_MINOR_1;
}
snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s%s", major, minor,
- SSH_VERSION, newline);
+ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION, newline);
server_version_string = xstrdup(buf);
/* Send our protocol version identification. */
@@ -1627,7 +1627,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 -up openssh-5.9p0/sshd_config.0.vendor openssh-5.9p0/sshd_config.0
--- openssh-5.9p0/sshd_config.0.vendor 2011-09-03 20:24:37.524438185 +0200
+++ openssh-5.9p0/sshd_config.0 2011-09-03 20:24:39.677508255 +0200
@@ -556,6 +556,11 @@ DESCRIPTION
Defines the number of bits in the ephemeral protocol version 1
server key. The minimum value is 512, and the default is 1024.
+ ShowPatchLevel
+ Specifies whether sshd will display the specific patch level of
+ the binary in the server identification string. The patch level
+ is set at compile-time. The default is M-bM-^@M-^\noM-bM-^@M-^].
+
StrictModes
Specifies whether sshd(8) should check file modes and ownership
of the user's files and home directory before accepting login.
diff -up openssh-5.9p0/sshd_config.5.vendor openssh-5.9p0/sshd_config.5
--- openssh-5.9p0/sshd_config.5.vendor 2011-09-03 20:24:37.640442022 +0200
+++ openssh-5.9p0/sshd_config.5 2011-09-03 20:24:40.176544206 +0200
@@ -952,6 +952,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.9p0/sshd_config.vendor openssh-5.9p0/sshd_config
--- openssh-5.9p0/sshd_config.vendor 2011-09-03 20:24:37.770439735 +0200
+++ openssh-5.9p0/sshd_config 2011-09-03 20:24:40.278628002 +0200
@@ -120,6 +120,7 @@ X11Forwarding yes
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
+#ShowPatchLevel no
#UseDNS yes
#PidFile /var/run/sshd.pid
#MaxStartups 10

View File

@ -18,3 +18,4 @@ patch -sp0 << EOF
extern const EVP_CIPHER *evp_ssh1_bf(void);
extern const EVP_CIPHER *evp_ssh1_3des(void);
EOF
echo "Well done."

View File

@ -78,10 +78,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.8p2
%define openssh_rel 21
%define openssh_ver 5.9p1
%define openssh_rel 1
%define pam_ssh_agent_ver 0.9.2
%define pam_ssh_agent_rel 31
%define pam_ssh_agent_rel 32
Summary: An open source implementation of SSH protocol versions 1 and 2
Name: openssh
@ -108,98 +108,100 @@ Source10: sshd.socket
Source11: sshd.service
Source13: sshd-keygen
Patch99: openssh-5.8p1-wIm.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1635 (WONTFIX)
Patch0: openssh-5.6p1-redhat.patch
# Internal debug
Patch0: openssh-5.8p1-wIm.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1872
Patch100: openssh-5.8p1-fingerprint.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1879
Patch200: openssh-5.8p1-exit.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1894
Patch300: openssh-5.8p1-getaddrinfo.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1402
Patch8: openssh-5.8p1-audit0.patch
Patch1: openssh-5.8p1-audit1.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
Patch101: openssh-5.8p1-getaddrinfo.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1889
Patch6: openssh-5.8p1-packet.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1890 (WONTFIX) need integration to prng helper
Patch7: openssh-5.8p1-entropy.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1640 (WONTFIX)
Patch9: openssh-5.8p1-vendor.patch
Patch102: openssh-5.8p1-packet.patch
#?
Patch103: openssh-5.9p1-2auth.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1402
Patch200: openssh-5.8p1-audit0.patch
# -"-
Patch201: openssh-5.9p1-audit1.patch
# -"-
Patch202: openssh-5.9p1-audit2.patch
# -"-
Patch203: openssh-5.9p1-audit3.patch
# -"-
Patch204: openssh-5.9p1-audit4.patch
# -"-
Patch205: openssh-5.9p1-audit5.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=1663
Patch20: openssh-5.8p1-authorized-keys-command.patch
#?-- unwanted child :(
Patch21: openssh-5.8p1-ldap.patch
# #-mail-conf
# Patch22: openssh-5.8p1-selinux.patch
Patch300: pam_ssh_agent_auth-0.9-build.patch
Patch301: pam_ssh_agent_auth-0.9.2-seteuid.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1641 (WONTFIX)
Patch23: openssh-5.8p1-selinux-role.patch
Patch400: openssh-5.9p1-role.patch
#?
Patch24: openssh-5.8p1-mls.patch
# #https://bugzilla.mindrot.org/show_bug.cgi?id=1614
# Patch25: openssh-5.6p1-selabel.patch
#was https://bugzilla.mindrot.org/show_bug.cgi?id=1637
Patch401: openssh-5.9p1-mls.patch
#?
Patch26: openssh-5.8p1-sftpcontext.patch
Patch402: openssh-5.9p1-sftp-chroot.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1663
Patch500: openssh-5.9p1-akc.patch
#?-- unwanted child :(
Patch501: openssh-5.9p1-ldap.patch
#?
Patch502: openssh-5.9p1-keycat.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1668
Patch30: openssh-5.6p1-keygen.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1644
Patch31: openssh-5.2p1-allow-ip-opts.patch
Patch600: openssh-5.9p1-keygen.patch
#http6://bugzilla.mindrot.org/show_bug.cgi?id=1644
Patch601: openssh-5.2p1-allow-ip-opts.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1701
Patch32: openssh-5.8p1-randclean.patch
# #https://bugzilla.mindrot.org/show_bug.cgi?id=1636
# Patch33: openssh-5.1p1-log-in-chroot.patch
Patch602: openssh-5.9p1-randclean.patch
#http://cvsweb.netbsd.org/cgi-bin/cvsweb.cgi/src/crypto/dist/ssh/Attic/sftp-glob.c.diff?r1=1.13&r2=1.13.12.1&f=h
Patch35: openssh-5.8p1-glob.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1891
Patch36: openssh-5.8p1-pwchange.patch
Patch603: openssh-5.8p1-glob.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1893
Patch37: openssh-5.8p1-keyperm.patch
#?
Patch50: openssh-5.8p1-fips.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1789
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
#?
Patch58: openssh-5.8p1-keycat.patch
#http://www.sxw.org.uk/computing/patches/openssh.html
Patch60: openssh-5.8p1-gsskex.patch
#?
Patch61: openssh-5.8p1-gssapi-canohost.patch
#?
Patch62: openssh-5.8p1-localdomain.patch
#http://www.mail-archive.com/kerberos@mit.edu/msg17591.html
Patch63: openssh-5.8p2-force_krb.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1780
Patch64: openssh-5.8p2-kuserok.patch
Patch604: openssh-5.8p1-keyperm.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1329 (WONTFIX)
Patch65: openssh-5.8p2-remove-stale-control-socket.patch
Patch605: openssh-5.8p2-remove-stale-control-socket.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1925
Patch66: openssh-5.8p2-ipv6man.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1919
Patch67: openssh-5.8p2-unconfined.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1924
Patch68: openssh-5.8p2-sesftplog.patch
Patch606: openssh-5.9p1-ipv6man.patch
#?
Patch69: openssh-5.8p2-askpass-ld.patch
Patch607: openssh-5.8p2-sigpipe.patch
#?
Patch70: openssh-5.8p2-sigpipe.patch
Patch608: openssh-5.8p2-askpass-ld.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1789
Patch609: openssh-5.5p1-x11.patch
#?
Patch700: openssh-5.9p1-fips.patch
#?
Patch701: openssh-5.6p1-exit-deadlock.patch
#?
Patch702: openssh-5.1p1-askpass-progress.patch
#?
Patch703: openssh-4.3p2-askpass-grab-info.patch
#?
Patch704: openssh-5.2p1-edns.patch
#?
Patch705: openssh-5.1p1-scp-manpage.patch
#?
Patch706: openssh-5.8p1-localdomain.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1635 (WONTFIX)
Patch707: openssh-5.9p1-redhat.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1890 (WONTFIX) need integration to prng helper which is discontinued :)
Patch708: openssh-5.9p1-entropy.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1640 (WONTFIX)
Patch709: openssh-5.9p1-vendor.patch
#http://www.sxw.org.uk/computing/patches/openssh.html
Patch800: openssh-5.9p1-gsskex.patch
#http://www.mail-archive.com/kerberos@mit.edu/msg17591.html
Patch801: openssh-5.8p2-force_krb.patch
#?
Patch900: openssh-5.8p1-gssapi-canohost.patch
#https://bugzilla.mindrot.org/show_bug.cgi?id=1780
Patch901: openssh-5.9p1-kuserok.patch
#---
#https://bugzilla.mindrot.org/show_bug.cgi?id=1604
# sctp
@ -380,66 +382,68 @@ The module is most useful for su and sudo service stacks.
%prep
%setup -q -a 4
#Do not enable by default
###%patch99 -p1 -b .wIm
###%patch0 -p1 -b .wIm
%patch0 -p1 -b .redhat
%patch100 -p1 -b .fingerprint
%patch200 -p1 -b .exit
%patch300 -p1 -b .getaddrinfo
%patch8 -p1 -b .audit0
%patch1 -p1 -b .audit1
%patch2 -p1 -b .audit2
%patch3 -p1 -b .audit3
%patch4 -p1 -b .audit4
%patch5 -p1 -b .audit5
%patch6 -p1 -b .packet
%patch7 -p1 -b .entropy
%patch9 -p1 -b .vendor
%patch101 -p1 -b .getaddrinfo
%patch102 -p1 -b .packet
%patch103 -p1 -b .2auth
%patch200 -p1 -b .audit0
%patch201 -p1 -b .audit1
%patch202 -p1 -b .audit2
%patch203 -p1 -b .audit3
%patch204 -p1 -b .audit4
%patch205 -p1 -b .audit5
%if %{pam_ssh_agent}
pushd pam_ssh_agent_auth-%{pam_ssh_agent_ver}
%patch10 -p1 -b .psaa-build
%patch11 -p1 -b .psaa-seteuid
%patch300 -p1 -b .psaa-build
%patch301 -p1 -b .psaa-seteuid
# Remove duplicate headers
rm -f $(cat %{SOURCE5})
popd
%endif
%patch20 -p1 -b .akc
%if %{ldap}
%patch21 -p1 -b .ldap
%endif
%if %{WITH_SELINUX}
#SELinux
# %patch22 -p1 -b .selinux
%patch23 -p1 -b .role
%patch24 -p1 -b .mls
%patch26 -p1 -b .sftpcontext
%endif
%patch30 -p1 -b .keygen
%patch31 -p1 -b .ip-opts
%patch32 -p1 -b .randclean
%patch35 -p1 -b .glob
%patch36 -p1 -b .pwchange
%patch37 -p1 -b .keyperm
%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
%patch58 -p1 -b .keycat
%patch60 -p1 -b .gsskex
%patch61 -p1 -b .canohost
%patch62 -p1 -b .localdomain
%patch63 -p1 -b .force_krb
%patch64 -p1 -b .kuserok
%patch65 -p1 -b .remove_stale
%patch66 -p1 -b .ipv6man
%patch67 -p1 -b .unconfined
%patch68 -p1 -b .sesftplog
%patch69 -p1 -b .askpass-ld
%patch70 -p1 -b .sigpipe
%if %{WITH_SELINUX}
%patch400 -p1 -b .role
%patch401 -p1 -b .mls
%patch402 -p1 -b .sftp-chroot
%endif
%patch500 -p1 -b .akc
%if %{ldap}
%patch501 -p1 -b .ldap
%endif
%patch502 -p1 -b .keycat
%patch600 -p1 -b .keygen
%patch601 -p1 -b .ip-opts
%patch602 -p1 -b .randclean
%patch603 -p1 -b .glob
%patch604 -p1 -b .keyperm
%patch605 -p1 -b .remove_stale
%patch606 -p1 -b .ipv6man
%patch607 -p1 -b .sigpipe
%patch608 -p1 -b .askpass-ld
%patch609 -p1 -b .x11
%patch700 -p1 -b .fips
%patch701 -p1 -b .exit-deadlock
%patch702 -p1 -b .progress
%patch703 -p1 -b .grab-info
%patch704 -p1 -b .edns
%patch705 -p1 -b .manpage
%patch706 -p1 -b .localdomain
%patch707 -p1 -b .redhat
%patch708 -p1 -b .entropy
%patch709 -p1 -b .vendor
%patch800 -p1 -b .gsskex
%patch801 -p1 -b .force_krb
%patch900 -p1 -b .canohost
%patch901 -p1 -b .kuserok
autoreconf
pushd pam_ssh_agent_auth-%{pam_ssh_agent_ver}
@ -675,7 +679,7 @@ fi
%files
%defattr(-,root,root)
%doc CREDITS ChangeLog INSTALL LICENCE OVERVIEW PROTOCOL* README README.platform README.privsep README.tun README.dns TODO WARNING*
%doc CREDITS ChangeLog INSTALL LICENCE OVERVIEW PROTOCOL* README README.platform README.privsep README.tun README.dns TODO
%attr(0755,root,root) %dir %{_sysconfdir}/ssh
%attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/moduli
%if ! %{rescue}

View File

@ -1,2 +1,2 @@
123003edd779504e12e1c8b58e7ce5dc openssh-5.8p2-noacss.tar.bz2
085cfbb262f1b8b875aadea6fba60b1b openssh-5.9p1-noacss.tar.bz2
b68f1c385d7885fbe2c3626bf77aa3d6 pam_ssh_agent_auth-0.9.2.tar.bz2