cleanup spec file and patches
This commit is contained in:
parent
c276d31b49
commit
1d76d11f64
@ -1,17 +0,0 @@
|
||||
Don't audit SSH_INVALID_USER twice.
|
||||
|
||||
PRIVSEP(getpwnamallow()) a few lines above already did this.
|
||||
|
||||
diff -ur openssh/auth2.c openssh-5.8p1/auth2.c
|
||||
--- openssh/auth2.c 2011-03-02 02:32:52.383773622 +0100
|
||||
+++ openssh-5.8p1/auth2.c 2011-03-02 03:32:34.585110911 +0100
|
||||
@@ -250,9 +250,6 @@
|
||||
} else {
|
||||
logit("input_userauth_request: invalid user %s", user);
|
||||
authctxt->pw = fakepw();
|
||||
-#ifdef SSH_AUDIT_EVENTS
|
||||
- PRIVSEP(audit_event(SSH_INVALID_USER));
|
||||
-#endif
|
||||
}
|
||||
#ifdef USE_PAM
|
||||
if (options.use_pam)
|
@ -1,353 +0,0 @@
|
||||
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 *);
|
@ -1,12 +0,0 @@
|
||||
diff -up openssh-5.9p1/contrib/ssh-copy-id.restorecon openssh-5.9p1/contrib/ssh-copy-id
|
||||
--- openssh-5.9p1/contrib/ssh-copy-id.restorecon 2011-08-17 04:05:49.000000000 +0200
|
||||
+++ openssh-5.9p1/contrib/ssh-copy-id 2011-11-21 08:40:56.000000000 +0100
|
||||
@@ -41,7 +41,7 @@ fi
|
||||
# strip any trailing colon
|
||||
host=`echo $1 | sed 's/:$//'`
|
||||
|
||||
-{ eval "$GET_ID" ; } | ssh $host "umask 077; test -d ~/.ssh || mkdir ~/.ssh ; cat >> ~/.ssh/authorized_keys" || exit 1
|
||||
+{ eval "$GET_ID" ; } | ssh $host "umask 077; test -d ~/.ssh || mkdir ~/.ssh ; cat >> ~/.ssh/authorized_keys && (test -x /sbin/restorecon && /sbin/restorecon ~/.ssh ~/.ssh/authorized_keys >/dev/null 2>&1 || true)" || exit 1
|
||||
|
||||
cat <<EOF
|
||||
Now try logging into the machine, with "ssh '$host'", and check in:
|
@ -1,80 +0,0 @@
|
||||
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)? ");
|
@ -1,321 +0,0 @@
|
||||
diff -up openssh-5.9p1/Makefile.in.sesandbox openssh-5.9p1/Makefile.in
|
||||
--- openssh-5.9p1/Makefile.in.sesandbox 2011-09-19 04:10:05.706521484 +0200
|
||||
+++ openssh-5.9p1/Makefile.in 2011-09-19 04:10:15.092646473 +0200
|
||||
@@ -90,7 +90,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw
|
||||
loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
|
||||
sftp-server.o sftp-common.o \
|
||||
roaming_common.o roaming_serv.o \
|
||||
- sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o
|
||||
+ sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o sandbox-selinux.o
|
||||
|
||||
MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out
|
||||
MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5
|
||||
diff -up openssh-5.9p1/configure.ac.sesandbox openssh-5.9p1/configure.ac
|
||||
--- openssh-5.9p1/configure.ac.sesandbox 2011-08-18 06:48:24.000000000 +0200
|
||||
+++ openssh-5.9p1/configure.ac 2011-09-19 04:10:15.193521356 +0200
|
||||
@@ -2476,7 +2476,7 @@ AC_SUBST([SSH_PRIVSEP_USER])
|
||||
# Decide which sandbox style to use
|
||||
sandbox_arg=""
|
||||
AC_ARG_WITH([sandbox],
|
||||
- [ --with-sandbox=style Specify privilege separation sandbox (no, darwin, rlimit, systrace)],
|
||||
+ [ --with-sandbox=style Specify privilege separation sandbox (no, darwin, rlimit, systrace, selinux)],
|
||||
[
|
||||
if test "x$withval" = "xyes" ; then
|
||||
sandbox_arg=""
|
||||
@@ -2499,6 +2499,10 @@ elif test "x$sandbox_arg" = "xdarwin" ||
|
||||
AC_MSG_ERROR([Darwin seatbelt sandbox requires sandbox.h and sandbox_init function])
|
||||
SANDBOX_STYLE="darwin"
|
||||
AC_DEFINE([SANDBOX_DARWIN], [1], [Sandbox using Darwin sandbox_init(3)])
|
||||
+elif test "x$sandbox_arg" = "xselinux" || \
|
||||
+ test "x$WITH_SELINUX" = "x1"; then
|
||||
+ SANDBOX_STYLE="selinux"
|
||||
+ AC_DEFINE([SANDBOX_SELINUX], [1], [Sandbox using selinux(8)])
|
||||
elif test "x$sandbox_arg" = "xrlimit" || \
|
||||
( test -z "$sandbox_arg" && test "x$ac_cv_func_setrlimit" = "xyes" ) ; then
|
||||
test "x$ac_cv_func_setrlimit" != "xyes" && \
|
||||
diff -up openssh-5.9p1/openbsd-compat/port-linux.c.sesandbox openssh-5.9p1/openbsd-compat/port-linux.c
|
||||
--- openssh-5.9p1/openbsd-compat/port-linux.c.sesandbox 2011-09-19 04:10:14.731521450 +0200
|
||||
+++ openssh-5.9p1/openbsd-compat/port-linux.c 2011-09-19 04:10:15.292521265 +0200
|
||||
@@ -459,24 +459,24 @@ ssh_selinux_setup_pty(char *pwname, cons
|
||||
debug3("%s: done", __func__);
|
||||
}
|
||||
|
||||
-void
|
||||
+int
|
||||
ssh_selinux_change_context(const char *newname)
|
||||
{
|
||||
- int len, newlen;
|
||||
+ int len, newlen, rv = -1;
|
||||
char *oldctx, *newctx, *cx;
|
||||
void (*switchlog) (const char *fmt,...) = logit;
|
||||
|
||||
if (!ssh_selinux_enabled())
|
||||
- return;
|
||||
+ return -2;
|
||||
|
||||
if (getcon((security_context_t *)&oldctx) < 0) {
|
||||
logit("%s: getcon failed with %s", __func__, strerror(errno));
|
||||
- return;
|
||||
+ return -1;
|
||||
}
|
||||
if ((cx = index(oldctx, ':')) == NULL || (cx = index(cx + 1, ':')) ==
|
||||
NULL) {
|
||||
logit ("%s: unparseable context %s", __func__, oldctx);
|
||||
- return;
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -484,8 +484,10 @@ ssh_selinux_change_context(const char *n
|
||||
* security context.
|
||||
*/
|
||||
if (strncmp(cx, SSH_SELINUX_UNCONFINED_TYPE,
|
||||
- sizeof(SSH_SELINUX_UNCONFINED_TYPE) - 1) == 0)
|
||||
+ sizeof(SSH_SELINUX_UNCONFINED_TYPE) - 1) == 0) {
|
||||
switchlog = debug3;
|
||||
+ rv = -2;
|
||||
+ }
|
||||
|
||||
newlen = strlen(oldctx) + strlen(newname) + 1;
|
||||
newctx = xmalloc(newlen);
|
||||
@@ -499,8 +501,11 @@ ssh_selinux_change_context(const char *n
|
||||
if (setcon(newctx) < 0)
|
||||
switchlog("%s: setcon %s from %s failed with %s", __func__,
|
||||
newctx, oldctx, strerror(errno));
|
||||
+ else
|
||||
+ rv = 0;
|
||||
xfree(oldctx);
|
||||
xfree(newctx);
|
||||
+ return rv;
|
||||
}
|
||||
|
||||
void
|
||||
diff -up openssh-5.9p1/openbsd-compat/port-linux.h.sesandbox openssh-5.9p1/openbsd-compat/port-linux.h
|
||||
--- openssh-5.9p1/openbsd-compat/port-linux.h.sesandbox 2011-09-19 04:10:14.817647868 +0200
|
||||
+++ openssh-5.9p1/openbsd-compat/port-linux.h 2011-09-19 04:10:15.401648009 +0200
|
||||
@@ -23,7 +23,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 *);
|
||||
+int ssh_selinux_change_context(const char *);
|
||||
void ssh_selinux_chopy_context(void);
|
||||
void ssh_selinux_setfscreatecon(const char *);
|
||||
#endif
|
||||
diff -up openssh-5.9p1/sandbox-darwin.c.sesandbox openssh-5.9p1/sandbox-darwin.c
|
||||
--- openssh-5.9p1/sandbox-darwin.c.sesandbox 2011-06-26 23:18:21.000000000 +0200
|
||||
+++ openssh-5.9p1/sandbox-darwin.c 2011-09-19 04:10:15.490523231 +0200
|
||||
@@ -83,6 +83,12 @@ ssh_sandbox_child(struct ssh_sandbox *bo
|
||||
}
|
||||
|
||||
void
|
||||
+ssh_sandbox_privileged_child(struct ssh_sandbox *box)
|
||||
+{
|
||||
+ /* empty */
|
||||
+}
|
||||
+
|
||||
+void
|
||||
ssh_sandbox_parent_finish(struct ssh_sandbox *box)
|
||||
{
|
||||
free(box);
|
||||
diff -up openssh-5.9p1/sandbox-null.c.sesandbox openssh-5.9p1/sandbox-null.c
|
||||
--- openssh-5.9p1/sandbox-null.c.sesandbox 2011-06-23 11:45:51.000000000 +0200
|
||||
+++ openssh-5.9p1/sandbox-null.c 2011-09-19 04:10:15.599458687 +0200
|
||||
@@ -58,6 +58,12 @@ ssh_sandbox_child(struct ssh_sandbox *bo
|
||||
}
|
||||
|
||||
void
|
||||
+ssh_sandbox_privileged_child(struct ssh_sandbox *box)
|
||||
+{
|
||||
+ /* empty */
|
||||
+}
|
||||
+
|
||||
+void
|
||||
ssh_sandbox_parent_finish(struct ssh_sandbox *box)
|
||||
{
|
||||
free(box);
|
||||
diff -up openssh-5.9p1/sandbox-rlimit.c.sesandbox openssh-5.9p1/sandbox-rlimit.c
|
||||
--- openssh-5.9p1/sandbox-rlimit.c.sesandbox 2011-06-23 11:45:51.000000000 +0200
|
||||
+++ openssh-5.9p1/sandbox-rlimit.c 2011-09-19 04:10:16.077647289 +0200
|
||||
@@ -78,6 +78,12 @@ ssh_sandbox_child(struct ssh_sandbox *bo
|
||||
}
|
||||
|
||||
void
|
||||
+ssh_sandbox_privileged_child(struct ssh_sandbox *box)
|
||||
+{
|
||||
+ /* empty */
|
||||
+}
|
||||
+
|
||||
+void
|
||||
ssh_sandbox_parent_finish(struct ssh_sandbox *box)
|
||||
{
|
||||
free(box);
|
||||
diff -up openssh-5.9p1/sandbox-selinux.c.sesandbox openssh-5.9p1/sandbox-selinux.c
|
||||
--- openssh-5.9p1/sandbox-selinux.c.sesandbox 2011-09-19 04:10:16.179526059 +0200
|
||||
+++ openssh-5.9p1/sandbox-selinux.c 2011-09-19 04:39:00.058646230 +0200
|
||||
@@ -0,0 +1,122 @@
|
||||
+/* $Id: sandbox-selinux.c,v 1.0 2011/01/17 10:15:30 jfch Exp $ */
|
||||
+
|
||||
+/*
|
||||
+ * Copyright 2011 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>
|
||||
+ */
|
||||
+
|
||||
+
|
||||
+#include "includes.h"
|
||||
+
|
||||
+#ifdef SANDBOX_SELINUX
|
||||
+
|
||||
+#include <sys/types.h>
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <stdarg.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <unistd.h>
|
||||
+#include <sys/resource.h>
|
||||
+
|
||||
+#include "log.h"
|
||||
+#include "ssh-sandbox.h"
|
||||
+#include "xmalloc.h"
|
||||
+#include "openbsd-compat/port-linux.h"
|
||||
+
|
||||
+/* selinux based sandbox */
|
||||
+
|
||||
+struct ssh_sandbox {
|
||||
+ pid_t child_pid;
|
||||
+};
|
||||
+
|
||||
+struct ssh_sandbox *
|
||||
+ssh_sandbox_init(void)
|
||||
+{
|
||||
+ struct ssh_sandbox *box;
|
||||
+
|
||||
+ /*
|
||||
+ * Strictly, we don't need to maintain any state here but we need
|
||||
+ * to return non-NULL to satisfy the API.
|
||||
+ */
|
||||
+ debug3("selinux sandbox init");
|
||||
+ box = xcalloc(1, sizeof(*box));
|
||||
+ box->child_pid = 0;
|
||||
+ return box;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+ssh_sandbox_child(struct ssh_sandbox *box)
|
||||
+{
|
||||
+ struct rlimit rl_zero;
|
||||
+
|
||||
+ rl_zero.rlim_cur = rl_zero.rlim_max = 0;
|
||||
+
|
||||
+ if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1)
|
||||
+ fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s",
|
||||
+ __func__, strerror(errno));
|
||||
+ if (setrlimit(RLIMIT_NOFILE, &rl_zero) == -1)
|
||||
+ fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s",
|
||||
+ __func__, strerror(errno));
|
||||
+#ifdef HAVE_RLIMIT_NPROC
|
||||
+ if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1)
|
||||
+ fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s",
|
||||
+ __func__, strerror(errno));
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+ssh_sandbox_privileged_child(struct ssh_sandbox *box)
|
||||
+{
|
||||
+ switch (ssh_selinux_change_context("sshd_net_t")) {
|
||||
+ case 0:
|
||||
+ debug3("selinux sandbox child sucessfully enabled");
|
||||
+ break;
|
||||
+ case -2:
|
||||
+ logit("selinux sandbox not useful");
|
||||
+ break;
|
||||
+ case -1:
|
||||
+ fatal("cannot set up selinux sandbox");
|
||||
+ default:
|
||||
+ fatal("inmternal error in selinux sandbox");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+ssh_sandbox_parent_finish(struct ssh_sandbox *box)
|
||||
+{
|
||||
+ free(box);
|
||||
+ debug3("%s: finished", __func__);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid)
|
||||
+{
|
||||
+ debug3("selinux sandbox parent sucessfully enabled");
|
||||
+ box->child_pid = child_pid;
|
||||
+}
|
||||
+
|
||||
+#endif /* SANDBOX_NULL */
|
||||
diff -up openssh-5.9p1/sandbox-systrace.c.sesandbox openssh-5.9p1/sandbox-systrace.c
|
||||
--- openssh-5.9p1/sandbox-systrace.c.sesandbox 2011-08-05 22:16:23.000000000 +0200
|
||||
+++ openssh-5.9p1/sandbox-systrace.c 2011-09-19 04:10:16.268646532 +0200
|
||||
@@ -109,6 +109,12 @@ ssh_sandbox_child(struct ssh_sandbox *bo
|
||||
close(box->child_sock);
|
||||
}
|
||||
|
||||
+void
|
||||
+ssh_sandbox_privileged_child(struct ssh_sandbox *box)
|
||||
+{
|
||||
+ /* empty */
|
||||
+}
|
||||
+
|
||||
static void
|
||||
ssh_sandbox_parent(struct ssh_sandbox *box, pid_t child_pid,
|
||||
const struct sandbox_policy *allowed_syscalls)
|
||||
diff -up openssh-5.9p1/ssh-sandbox.h.sesandbox openssh-5.9p1/ssh-sandbox.h
|
||||
--- openssh-5.9p1/ssh-sandbox.h.sesandbox 2011-06-23 11:45:51.000000000 +0200
|
||||
+++ openssh-5.9p1/ssh-sandbox.h 2011-09-19 04:10:16.392523931 +0200
|
||||
@@ -19,5 +19,6 @@ struct ssh_sandbox;
|
||||
|
||||
struct ssh_sandbox *ssh_sandbox_init(void);
|
||||
void ssh_sandbox_child(struct ssh_sandbox *);
|
||||
+void ssh_sandbox_privileged_child(struct ssh_sandbox *);
|
||||
void ssh_sandbox_parent_finish(struct ssh_sandbox *);
|
||||
void ssh_sandbox_parent_preauth(struct ssh_sandbox *, pid_t);
|
||||
diff -up openssh-5.9p1/sshd.c.sesandbox openssh-5.9p1/sshd.c
|
||||
--- openssh-5.9p1/sshd.c.sesandbox 2011-09-19 04:10:14.564467584 +0200
|
||||
+++ openssh-5.9p1/sshd.c 2011-09-19 04:36:43.324520132 +0200
|
||||
@@ -728,10 +730,12 @@ privsep_preauth(Authctxt *authctxt)
|
||||
set_log_handler(mm_log_handler, pmonitor);
|
||||
|
||||
/* Demote the child */
|
||||
- if (getuid() == 0 || geteuid() == 0)
|
||||
+ if (getuid() == 0 || geteuid() == 0) {
|
||||
+ ssh_sandbox_privileged_child(box);
|
||||
privsep_preauth_child();
|
||||
+ }
|
||||
setproctitle("%s", "[net]");
|
||||
if (box != NULL) {
|
||||
ssh_sandbox_child(box);
|
||||
xfree(box);
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
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));
|
||||
}
|
@ -1,579 +0,0 @@
|
||||
diff -up openssh-6.1p1/auth2-pubkey.c.akc openssh-6.1p1/auth2-pubkey.c
|
||||
--- openssh-6.1p1/auth2-pubkey.c.akc 2013-02-14 17:46:45.259546968 +0100
|
||||
+++ openssh-6.1p1/auth2-pubkey.c 2013-02-14 17:48:19.072137541 +0100
|
||||
@@ -27,9 +27,13 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
+#include <sys/wait.h>
|
||||
|
||||
+#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
+#include <paths.h>
|
||||
#include <pwd.h>
|
||||
+#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
@@ -260,7 +264,7 @@ match_principals_file(char *file, struct
|
||||
if (strcmp(cp, cert->principals[i]) == 0) {
|
||||
debug3("matched principal \"%.100s\" "
|
||||
"from file \"%s\" on line %lu",
|
||||
- cert->principals[i], file, linenum);
|
||||
+ cert->principals[i], file, linenum);
|
||||
if (auth_parse_options(pw, line_opts,
|
||||
file, linenum) != 1)
|
||||
continue;
|
||||
@@ -273,31 +277,22 @@ match_principals_file(char *file, struct
|
||||
fclose(f);
|
||||
restore_uid();
|
||||
return 0;
|
||||
-}
|
||||
+}
|
||||
|
||||
-/* return 1 if user allows given key */
|
||||
+/*
|
||||
+ * Checks whether key is allowed in authorized_keys-format file,
|
||||
+ * returns 1 if the key is allowed or 0 otherwise.
|
||||
+ */
|
||||
static int
|
||||
-user_key_allowed2(struct passwd *pw, Key *key, char *file)
|
||||
+check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
|
||||
{
|
||||
char line[SSH_MAX_PUBKEY_BYTES];
|
||||
const char *reason;
|
||||
int found_key = 0;
|
||||
- FILE *f;
|
||||
u_long linenum = 0;
|
||||
Key *found;
|
||||
char *fp;
|
||||
|
||||
- /* Temporarily use the user's uid. */
|
||||
- temporarily_use_uid(pw);
|
||||
-
|
||||
- debug("trying public key file %s", file);
|
||||
- f = auth_openkeyfile(file, pw, options.strict_modes);
|
||||
-
|
||||
- if (!f) {
|
||||
- restore_uid();
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
found_key = 0;
|
||||
found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
|
||||
|
||||
@@ -390,8 +385,6 @@ user_key_allowed2(struct passwd *pw, Key
|
||||
break;
|
||||
}
|
||||
}
|
||||
- restore_uid();
|
||||
- fclose(f);
|
||||
key_free(found);
|
||||
if (!found_key)
|
||||
debug2("key not found");
|
||||
@@ -453,7 +446,180 @@ user_cert_trusted_ca(struct passwd *pw,
|
||||
return ret;
|
||||
}
|
||||
|
||||
-/* check whether given key is in .ssh/authorized_keys* */
|
||||
+/*
|
||||
+ * Checks whether key is allowed in file.
|
||||
+ * returns 1 if the key is allowed or 0 otherwise.
|
||||
+ */
|
||||
+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);
|
||||
+ if ((f = auth_openkeyfile(file, pw, options.strict_modes)) != NULL) {
|
||||
+ found_key = check_authkeys_file(f, file, key, pw);
|
||||
+ fclose(f);
|
||||
+ }
|
||||
+
|
||||
+ restore_uid();
|
||||
+ return found_key;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Checks whether key is allowed in output of command.
|
||||
+ * returns 1 if the key is allowed or 0 otherwise.
|
||||
+ */
|
||||
+static int
|
||||
+user_key_command_allowed2(struct passwd *user_pw, Key *key)
|
||||
+{
|
||||
+ FILE *f;
|
||||
+ int ok, found_key = 0;
|
||||
+ struct passwd *pw;
|
||||
+ struct stat st;
|
||||
+ int status, devnull, p[2], i;
|
||||
+ pid_t pid;
|
||||
+ char *username, errmsg[512];
|
||||
+
|
||||
+ if (options.authorized_keys_command == NULL ||
|
||||
+ options.authorized_keys_command[0] != '/')
|
||||
+ return 0;
|
||||
+
|
||||
+ if (options.authorized_keys_command_user == NULL) {
|
||||
+ error("No user for AuthorizedKeysCommand specified, skipping");
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ username = percent_expand(options.authorized_keys_command_user,
|
||||
+ "u", user_pw->pw_name, (char *)NULL);
|
||||
+ pw = getpwnam(username);
|
||||
+ if (pw == NULL) {
|
||||
+ error("AuthorizedKeyCommandUser \"%s\" not found: %s",
|
||||
+ username, strerror(errno));
|
||||
+ free(username);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ free(username);
|
||||
+
|
||||
+ temporarily_use_uid(pw);
|
||||
+
|
||||
+ if (stat(options.authorized_keys_command, &st) < 0) {
|
||||
+ error("Could not stat AuthorizedKeysCommand \"%s\": %s",
|
||||
+ options.authorized_keys_command, strerror(errno));
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (auth_secure_path(options.authorized_keys_command, &st, NULL, 0,
|
||||
+ errmsg, sizeof(errmsg)) != 0) {
|
||||
+ error("Unsafe AuthorizedKeysCommand: %s", errmsg);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (pipe(p) != 0) {
|
||||
+ error("%s: pipe: %s", __func__, strerror(errno));
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ debug3("Running AuthorizedKeysCommand: \"%s %s\" as \"%s\"",
|
||||
+ options.authorized_keys_command, user_pw->pw_name, pw->pw_name);
|
||||
+
|
||||
+ /*
|
||||
+ * Don't want to call this in the child, where it can fatal() and
|
||||
+ * run cleanup_exit() code.
|
||||
+ */
|
||||
+ restore_uid();
|
||||
+
|
||||
+ switch ((pid = fork())) {
|
||||
+ case -1: /* error */
|
||||
+ error("%s: fork: %s", __func__, strerror(errno));
|
||||
+ close(p[0]);
|
||||
+ close(p[1]);
|
||||
+ return 0;
|
||||
+ case 0: /* child */
|
||||
+ for (i = 0; i < NSIG; i++)
|
||||
+ signal(i, SIG_DFL);
|
||||
+
|
||||
+ if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
|
||||
+ error("%s: open %s: %s", __func__, _PATH_DEVNULL,
|
||||
+ strerror(errno));
|
||||
+ _exit(1);
|
||||
+ }
|
||||
+ /* Keep stderr around a while longer to catch errors */
|
||||
+ if (dup2(devnull, STDIN_FILENO) == -1 ||
|
||||
+ dup2(p[1], STDOUT_FILENO) == -1) {
|
||||
+ error("%s: dup2: %s", __func__, strerror(errno));
|
||||
+ _exit(1);
|
||||
+ }
|
||||
+ closefrom(STDERR_FILENO + 1);
|
||||
+
|
||||
+ /* Don't use permanently_set_uid() here to avoid fatal() */
|
||||
+ if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) {
|
||||
+ error("setresgid %u: %s", (u_int)pw->pw_gid,
|
||||
+ strerror(errno));
|
||||
+ _exit(1);
|
||||
+ }
|
||||
+ if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) {
|
||||
+ error("setresuid %u: %s", (u_int)pw->pw_uid,
|
||||
+ strerror(errno));
|
||||
+ _exit(1);
|
||||
+ }
|
||||
+ /* stdin is pointed to /dev/null at this point */
|
||||
+ if (dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
|
||||
+ error("%s: dup2: %s", __func__, strerror(errno));
|
||||
+ _exit(1);
|
||||
+ }
|
||||
+
|
||||
+ execl(options.authorized_keys_command,
|
||||
+ options.authorized_keys_command, user_pw->pw_name, NULL);
|
||||
+
|
||||
+ error("AuthorizedKeysCommand %s exec failed: %s",
|
||||
+ options.authorized_keys_command, strerror(errno));
|
||||
+ _exit(127);
|
||||
+ default: /* parent */
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ temporarily_use_uid(pw);
|
||||
+
|
||||
+ close(p[1]);
|
||||
+ if ((f = fdopen(p[0], "r")) == NULL) {
|
||||
+ error("%s: fdopen: %s", __func__, strerror(errno));
|
||||
+ close(p[0]);
|
||||
+ /* Don't leave zombie child */
|
||||
+ kill(pid, SIGTERM);
|
||||
+ while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
|
||||
+ ;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ ok = check_authkeys_file(f, options.authorized_keys_command, key, pw);
|
||||
+ fclose(f);
|
||||
+
|
||||
+ while (waitpid(pid, &status, 0) == -1) {
|
||||
+ if (errno != EINTR) {
|
||||
+ error("%s: waitpid: %s", __func__, strerror(errno));
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+ if (WIFSIGNALED(status)) {
|
||||
+ error("AuthorizedKeysCommand %s exited on signal %d",
|
||||
+ options.authorized_keys_command, WTERMSIG(status));
|
||||
+ goto out;
|
||||
+ } else if (WEXITSTATUS(status) != 0) {
|
||||
+ error("AuthorizedKeysCommand %s returned status %d",
|
||||
+ options.authorized_keys_command, WEXITSTATUS(status));
|
||||
+ goto out;
|
||||
+ }
|
||||
+ found_key = ok;
|
||||
+ out:
|
||||
+ restore_uid();
|
||||
+ return found_key;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Check whether key authenticates and authorises the user.
|
||||
+ */
|
||||
int
|
||||
user_key_allowed(struct passwd *pw, Key *key)
|
||||
{
|
||||
@@ -469,9 +635,17 @@ user_key_allowed(struct passwd *pw, Key
|
||||
if (success)
|
||||
return success;
|
||||
|
||||
+ success = user_key_command_allowed2(pw, key);
|
||||
+ if (success > 0)
|
||||
+ return success;
|
||||
+
|
||||
for (i = 0; !success && i < options.num_authkeys_files; i++) {
|
||||
+
|
||||
+ if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
|
||||
+ continue;
|
||||
file = expand_authorized_keys(
|
||||
options.authorized_keys_files[i], pw);
|
||||
+
|
||||
success = user_key_allowed2(pw, key, file);
|
||||
xfree(file);
|
||||
}
|
||||
diff -up openssh-6.1p1/auth.c.akc openssh-6.1p1/auth.c
|
||||
--- openssh-6.1p1/auth.c.akc 2013-02-14 17:46:45.189547274 +0100
|
||||
+++ openssh-6.1p1/auth.c 2013-02-14 17:46:45.273546907 +0100
|
||||
@@ -415,39 +415,41 @@ check_key_in_hostfiles(struct passwd *pw
|
||||
|
||||
|
||||
/*
|
||||
- * Check a given file for security. This is defined as all components
|
||||
+ * Check a given path for security. This is defined as all components
|
||||
* of the path to the file must be owned by either the owner of
|
||||
* of the file or root and no directories must be group or world writable.
|
||||
*
|
||||
* XXX Should any specific check be done for sym links ?
|
||||
*
|
||||
- * Takes an open file descriptor, the file name, a uid and and
|
||||
+ * Takes an the file name, its stat information (preferably from fstat() to
|
||||
+ * avoid races), the uid of the expected owner, their home directory and an
|
||||
* error buffer plus max size as arguments.
|
||||
*
|
||||
* Returns 0 on success and -1 on failure
|
||||
*/
|
||||
-static int
|
||||
-secure_filename(FILE *f, const char *file, struct passwd *pw,
|
||||
- char *err, size_t errlen)
|
||||
+int
|
||||
+auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
|
||||
+ uid_t uid, char *err, size_t errlen)
|
||||
{
|
||||
- uid_t uid = pw->pw_uid;
|
||||
char buf[MAXPATHLEN], homedir[MAXPATHLEN];
|
||||
char *cp;
|
||||
int comparehome = 0;
|
||||
struct stat st;
|
||||
|
||||
- if (realpath(file, buf) == NULL) {
|
||||
- snprintf(err, errlen, "realpath %s failed: %s", file,
|
||||
+ if (realpath(name, buf) == NULL) {
|
||||
+ snprintf(err, errlen, "realpath %s failed: %s", name,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
- if (realpath(pw->pw_dir, homedir) != NULL)
|
||||
+ if (pw_dir != NULL && realpath(pw_dir, homedir) != NULL)
|
||||
comparehome = 1;
|
||||
|
||||
- /* check the open file to avoid races */
|
||||
- if (fstat(fileno(f), &st) < 0 ||
|
||||
- (st.st_uid != 0 && st.st_uid != uid) ||
|
||||
- (st.st_mode & 022) != 0) {
|
||||
+ if (!S_ISREG(stp->st_mode)) {
|
||||
+ snprintf(err, errlen, "%s is not a regular file", buf);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ if ((stp->st_uid != 0 && stp->st_uid != uid) ||
|
||||
+ (stp->st_mode & 022) != 0) {
|
||||
snprintf(err, errlen, "bad ownership or modes for file %s",
|
||||
buf);
|
||||
return -1;
|
||||
@@ -483,6 +485,31 @@ secure_filename(FILE *f, const char *fil
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Version of secure_path() that accepts an open file descriptor to
|
||||
+ * avoid races.
|
||||
+ *
|
||||
+ * Returns 0 on success and -1 on failure
|
||||
+ */
|
||||
+static int
|
||||
+secure_filename(FILE *f, const char *file, struct passwd *pw,
|
||||
+ char *err, size_t errlen)
|
||||
+{
|
||||
+ uid_t uid = pw->pw_uid;
|
||||
+ char buf[MAXPATHLEN], homedir[MAXPATHLEN];
|
||||
+ char *cp;
|
||||
+ int comparehome = 0;
|
||||
+ struct stat st;
|
||||
+
|
||||
+ /* check the open file to avoid races */
|
||||
+ if (fstat(fileno(f), &st) < 0) {
|
||||
+ snprintf(err, errlen, "cannot stat file %s: %s",
|
||||
+ buf, strerror(errno));
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return auth_secure_path(file, &st, pw->pw_dir, pw->pw_uid, err, errlen);
|
||||
+}
|
||||
+
|
||||
static FILE *
|
||||
auth_openfile(const char *file, struct passwd *pw, int strict_modes,
|
||||
int log_missing, char *file_type)
|
||||
diff -up openssh-6.1p1/auth.h.akc openssh-6.1p1/auth.h
|
||||
--- openssh-6.1p1/auth.h.akc 2013-02-14 17:46:45.259546968 +0100
|
||||
+++ openssh-6.1p1/auth.h 2013-02-14 17:46:45.274546903 +0100
|
||||
@@ -125,6 +125,10 @@ int auth_rhosts_rsa_key_allowed(struct
|
||||
int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
|
||||
int user_key_allowed(struct passwd *, Key *);
|
||||
|
||||
+struct stat;
|
||||
+int auth_secure_path(const char *, struct stat *, const char *, uid_t,
|
||||
+ char *, size_t);
|
||||
+
|
||||
#ifdef KRB5
|
||||
int auth_krb5(Authctxt *authctxt, krb5_data *auth, char **client, krb5_data *);
|
||||
int auth_krb5_tgt(Authctxt *authctxt, krb5_data *tgt);
|
||||
diff -up openssh-6.1p1/servconf.c.akc openssh-6.1p1/servconf.c
|
||||
--- openssh-6.1p1/servconf.c.akc 2013-02-14 17:46:45.193547257 +0100
|
||||
+++ openssh-6.1p1/servconf.c 2013-02-14 17:46:45.274546903 +0100
|
||||
@@ -137,6 +137,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_user = NULL;
|
||||
options->zero_knowledge_password_authentication = -1;
|
||||
options->revoked_keys_file = NULL;
|
||||
options->trusted_user_ca_keys = NULL;
|
||||
@@ -331,6 +333,7 @@ typedef enum {
|
||||
sZeroKnowledgePasswordAuthentication, sHostCertificate,
|
||||
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
|
||||
sKexAlgorithms, sIPQoS, sVersionAddendum,
|
||||
+ sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
|
||||
sAuthenticationMethods,
|
||||
sDeprecated, sUnsupported
|
||||
} ServerOpCodes;
|
||||
@@ -457,6 +460,9 @@ static struct {
|
||||
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
|
||||
{ "ipqos", sIPQoS, SSHCFG_ALL },
|
||||
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
|
||||
+ { "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
|
||||
+ { "authorizedkeyscommandrunas", sAuthorizedKeysCommandUser, SSHCFG_ALL },
|
||||
+ { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
|
||||
{ "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
|
||||
{ NULL, sBadOption, 0 }
|
||||
};
|
||||
@@ -1520,6 +1526,26 @@ process_server_config_line(ServerOptions
|
||||
}
|
||||
return 0;
|
||||
|
||||
+ case sAuthorizedKeysCommand:
|
||||
+ len = strspn(cp, WHITESPACE);
|
||||
+ if (*activep && options->authorized_keys_command == NULL) {
|
||||
+ options->authorized_keys_command = xstrdup(cp + len);
|
||||
+ if (*options->authorized_keys_command != '/') {
|
||||
+ fatal("%.200s line %d: AuthorizedKeysCommand "
|
||||
+ "must be an absolute path",
|
||||
+ filename, linenum);
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+
|
||||
+ case sAuthorizedKeysCommandUser:
|
||||
+ charptr = &options->authorized_keys_command_user;
|
||||
+
|
||||
+ arg = strdelim(&cp);
|
||||
+ if (*activep && *charptr == NULL)
|
||||
+ *charptr = xstrdup(arg);
|
||||
+ break;
|
||||
+
|
||||
case sDeprecated:
|
||||
logit("%s line %d: Deprecated option %s",
|
||||
filename, linenum, arg);
|
||||
@@ -1670,6 +1696,8 @@ copy_set_server_options(ServerOptions *d
|
||||
M_CP_INTOPT(hostbased_uses_name_from_packet_only);
|
||||
M_CP_INTOPT(kbd_interactive_authentication);
|
||||
M_CP_INTOPT(zero_knowledge_password_authentication);
|
||||
+ M_CP_STROPT(authorized_keys_command);
|
||||
+ M_CP_STROPT(authorized_keys_command_user);
|
||||
M_CP_INTOPT(permit_root_login);
|
||||
M_CP_INTOPT(permit_empty_passwd);
|
||||
|
||||
@@ -1930,6 +1958,8 @@ dump_config(ServerOptions *o)
|
||||
dump_cfg_string(sAuthorizedPrincipalsFile,
|
||||
o->authorized_principals_file);
|
||||
dump_cfg_string(sVersionAddendum, o->version_addendum);
|
||||
+ dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command);
|
||||
+ dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user);
|
||||
|
||||
/* string arguments requiring a lookup */
|
||||
dump_cfg_string(sLogLevel, log_level_name(o->log_level));
|
||||
diff -up openssh-6.1p1/servconf.h.akc openssh-6.1p1/servconf.h
|
||||
--- openssh-6.1p1/servconf.h.akc 2013-02-14 17:46:45.194547252 +0100
|
||||
+++ openssh-6.1p1/servconf.h 2013-02-14 17:46:45.275546898 +0100
|
||||
@@ -167,6 +167,8 @@ typedef struct {
|
||||
char *revoked_keys_file;
|
||||
char *trusted_user_ca_keys;
|
||||
char *authorized_principals_file;
|
||||
+ char *authorized_keys_command;
|
||||
+ char *authorized_keys_command_user;
|
||||
|
||||
char *version_addendum; /* Appended to SSH banner */
|
||||
|
||||
diff -up openssh-6.1p1/sshd.c.akc openssh-6.1p1/sshd.c
|
||||
--- openssh-6.1p1/sshd.c.akc 2013-02-14 17:46:45.270546920 +0100
|
||||
+++ openssh-6.1p1/sshd.c 2013-02-14 17:46:45.276546894 +0100
|
||||
@@ -366,9 +366,20 @@ main_sigchld_handler(int sig)
|
||||
static void
|
||||
grace_alarm_handler(int sig)
|
||||
{
|
||||
+ pid_t pgid;
|
||||
+
|
||||
if (use_privsep && pmonitor != NULL && pmonitor->m_pid > 0)
|
||||
kill(pmonitor->m_pid, SIGALRM);
|
||||
|
||||
+ /*
|
||||
+ * Try to kill any processes that we have spawned, E.g. authorized
|
||||
+ * keys command helpers.
|
||||
+ */
|
||||
+ if ((pgid = getpgid(0)) == getpid()) {
|
||||
+ signal(SIGTERM, SIG_IGN);
|
||||
+ killpg(pgid, SIGTERM);
|
||||
+ }
|
||||
+
|
||||
/* Log error and exit. */
|
||||
sigdie("Timeout before authentication for %s", get_remote_ipaddr());
|
||||
}
|
||||
diff -up openssh-6.1p1/sshd_config.0.akc openssh-6.1p1/sshd_config.0
|
||||
--- openssh-6.1p1/sshd_config.0.akc 2012-08-29 02:53:04.000000000 +0200
|
||||
+++ openssh-6.1p1/sshd_config.0 2013-02-14 17:46:45.276546894 +0100
|
||||
@@ -71,6 +71,23 @@ DESCRIPTION
|
||||
|
||||
See PATTERNS in ssh_config(5) for more information on patterns.
|
||||
|
||||
+ AuthorizedKeysCommand
|
||||
+
|
||||
+ Specifies a program to be used for lookup of the user's
|
||||
+ public keys. The program will be invoked with its first
|
||||
+ argument the name of the user being authorized, and should produce
|
||||
+ on standard output AuthorizedKeys lines (see AUTHORIZED_KEYS
|
||||
+ in sshd(8)). By default (or when set to the empty string) there is no
|
||||
+ AuthorizedKeysCommand run. If the AuthorizedKeysCommand does not successfully
|
||||
+ authorize the user, authorization falls through to the
|
||||
+ AuthorizedKeysFile. Note that this option has an effect
|
||||
+ only with PubkeyAuthentication turned on.
|
||||
+
|
||||
+ AuthorizedKeysCommandRunAs
|
||||
+ Specifies the user under whose account the AuthorizedKeysCommand is run.
|
||||
+ Empty string (the default value) means the user being authorized
|
||||
+ is used.
|
||||
+
|
||||
AuthorizedKeysFile
|
||||
Specifies the file that contains the public keys that can be used
|
||||
for user authentication. The format is described in the
|
||||
@@ -402,7 +419,8 @@ DESCRIPTION
|
||||
Only a subset of keywords may be used on the lines following a
|
||||
Match keyword. Available keywords are AcceptEnv,
|
||||
AllowAgentForwarding, AllowGroups, AllowTcpForwarding,
|
||||
- AllowUsers, AuthorizedKeysFile, AuthorizedPrincipalsFile, Banner,
|
||||
+ AllowUsers, AuthorizedKeysFile, AuthorizedKeysCommand,
|
||||
+ AuthorizedKeysCommandRunAs, AuthorizedPrincipalsFile, Banner,
|
||||
ChrootDirectory, DenyGroups, DenyUsers, ForceCommand,
|
||||
GatewayPorts, GSSAPIAuthentication, HostbasedAuthentication,
|
||||
HostbasedUsesNameFromPacketOnly, KbdInteractiveAuthentication,
|
||||
diff -up openssh-6.1p1/sshd_config.5.akc openssh-6.1p1/sshd_config.5
|
||||
--- openssh-6.1p1/sshd_config.5.akc 2013-02-14 17:46:45.195547248 +0100
|
||||
+++ openssh-6.1p1/sshd_config.5 2013-02-14 17:46:45.277546890 +0100
|
||||
@@ -173,6 +173,20 @@ Note that each authentication method lis
|
||||
in the configuration.
|
||||
The default is not to require multiple authentication; successful completion
|
||||
of a single authentication method is sufficient.
|
||||
+.It Cm AuthorizedKeysCommand
|
||||
+Specifies a program to be used for lookup of the user's public keys.
|
||||
+The program will be invoked with a single argument of the username
|
||||
+being authenticated, and should produce on standard output zero or
|
||||
+more lines of authorized_keys output (see AUTHORIZED_KEYS in
|
||||
+.Xr sshd 8 )
|
||||
+If a key supplied by AuthorizedKeysCommand does not successfully authenticate
|
||||
+and authorize the user then public key authentication continues using the usual
|
||||
+.Cm AuthorizedKeysFile
|
||||
+files.
|
||||
+By default, no AuthorizedKeysCommand is run.
|
||||
+.It Cm AuthorizedKeysCommandUser
|
||||
+Specifies the user under whose account the AuthorizedKeysCommand is run.
|
||||
+The default is the user being authenticated.
|
||||
.It Cm AuthorizedKeysFile
|
||||
Specifies the file that contains the public keys that can be used
|
||||
for user authentication.
|
||||
@@ -734,6 +748,8 @@ Available keywords are
|
||||
.Cm AllowTcpForwarding ,
|
||||
.Cm AllowUsers ,
|
||||
.Cm AuthenticationMethods ,
|
||||
+.Cm AuthorizedKeysCommand ,
|
||||
+.Cm AuthorizedKeysCommandUser ,
|
||||
.Cm AuthorizedKeysFile ,
|
||||
.Cm AuthorizedPrincipalsFile ,
|
||||
.Cm Banner ,
|
||||
@@ -749,6 +765,7 @@ Available keywords are
|
||||
.Cm KerberosAuthentication ,
|
||||
.Cm MaxAuthTries ,
|
||||
.Cm MaxSessions ,
|
||||
+.Cm PubkeyAuthentication ,
|
||||
.Cm PasswordAuthentication ,
|
||||
.Cm PermitEmptyPasswords ,
|
||||
.Cm PermitOpen ,
|
||||
diff -up openssh-6.1p1/sshd_config.akc openssh-6.1p1/sshd_config
|
||||
--- openssh-6.1p1/sshd_config.akc 2012-07-31 04:21:34.000000000 +0200
|
||||
+++ openssh-6.1p1/sshd_config 2013-02-14 17:46:45.277546890 +0100
|
||||
@@ -49,6 +49,9 @@
|
||||
# but this is overridden so installations will only check .ssh/authorized_keys
|
||||
AuthorizedKeysFile .ssh/authorized_keys
|
||||
|
||||
+#AuthorizedKeysCommand none
|
||||
+#AuthorizedKeysCommandUser nobody
|
||||
+
|
||||
#AuthorizedPrincipalsFile none
|
||||
|
||||
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
|
@ -1,841 +0,0 @@
|
||||
diff --git a/auth.c b/auth.c
|
||||
index ee0cb05..1b2fc2b 100644
|
||||
--- a/auth.c
|
||||
+++ b/auth.c
|
||||
@@ -251,7 +251,8 @@ allowed_user(struct passwd * pw)
|
||||
}
|
||||
|
||||
void
|
||||
-auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
|
||||
+auth_log(Authctxt *authctxt, int authenticated, int partial,
|
||||
+ const char *method, const char *submethod, const char *info)
|
||||
{
|
||||
void (*authlog) (const char *fmt,...) = verbose;
|
||||
char *authmsg;
|
||||
@@ -268,12 +269,15 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
|
||||
|
||||
if (authctxt->postponed)
|
||||
authmsg = "Postponed";
|
||||
+ else if (partial)
|
||||
+ authmsg = "Partial";
|
||||
else
|
||||
authmsg = authenticated ? "Accepted" : "Failed";
|
||||
|
||||
- authlog("%s %s for %s%.100s from %.200s port %d%s",
|
||||
+ authlog("%s %s%s%s for %s%.100s from %.200s port %d%s",
|
||||
authmsg,
|
||||
method,
|
||||
+ submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod,
|
||||
authctxt->valid ? "" : "invalid user ",
|
||||
authctxt->user,
|
||||
get_remote_ipaddr(),
|
||||
@@ -303,7 +307,7 @@ auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
|
||||
* Check whether root logins are disallowed.
|
||||
*/
|
||||
int
|
||||
-auth_root_allowed(char *method)
|
||||
+auth_root_allowed(const char *method)
|
||||
{
|
||||
switch (options.permit_root_login) {
|
||||
case PERMIT_YES:
|
||||
diff --git a/auth.h b/auth.h
|
||||
index 0d786c4..29823bb 100644
|
||||
--- a/auth.h
|
||||
+++ b/auth.h
|
||||
@@ -64,6 +64,8 @@ struct Authctxt {
|
||||
#ifdef BSD_AUTH
|
||||
auth_session_t *as;
|
||||
#endif
|
||||
+ char **auth_methods; /* modified from server config */
|
||||
+ u_int num_auth_methods;
|
||||
#ifdef KRB5
|
||||
krb5_context krb5_ctx;
|
||||
krb5_ccache krb5_fwd_ccache;
|
||||
@@ -142,12 +144,17 @@ void disable_forwarding(void);
|
||||
void do_authentication(Authctxt *);
|
||||
void do_authentication2(Authctxt *);
|
||||
|
||||
-void auth_log(Authctxt *, int, char *, char *);
|
||||
-void userauth_finish(Authctxt *, int, char *);
|
||||
+void auth_log(Authctxt *, int, int, const char *, const char *,
|
||||
+ const char *);
|
||||
+void userauth_finish(Authctxt *, int, const char *, const char *);
|
||||
+int auth_root_allowed(const char *);
|
||||
+
|
||||
void userauth_send_banner(const char *);
|
||||
-int auth_root_allowed(char *);
|
||||
|
||||
char *auth2_read_banner(void);
|
||||
+int auth2_methods_valid(const char *, int);
|
||||
+int auth2_update_methods_lists(Authctxt *, const char *);
|
||||
+int auth2_setup_methods_lists(Authctxt *);
|
||||
|
||||
void privsep_challenge_enable(void);
|
||||
|
||||
diff --git a/auth1.c b/auth1.c
|
||||
index cc85aec..458a110 100644
|
||||
--- a/auth1.c
|
||||
+++ b/auth1.c
|
||||
@@ -253,7 +253,8 @@ do_authloop(Authctxt *authctxt)
|
||||
if (options.use_pam && (PRIVSEP(do_pam_account())))
|
||||
#endif
|
||||
{
|
||||
- auth_log(authctxt, 1, "without authentication", "");
|
||||
+ auth_log(authctxt, 1, 0, "without authentication",
|
||||
+ NULL, "");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -352,7 +353,8 @@ do_authloop(Authctxt *authctxt)
|
||||
|
||||
skip:
|
||||
/* Log before sending the reply */
|
||||
- auth_log(authctxt, authenticated, get_authname(type), info);
|
||||
+ auth_log(authctxt, authenticated, 0, get_authname(type),
|
||||
+ NULL, info);
|
||||
|
||||
if (client_user != NULL) {
|
||||
xfree(client_user);
|
||||
@@ -406,6 +408,11 @@ do_authentication(Authctxt *authctxt)
|
||||
authctxt->pw = fakepw();
|
||||
}
|
||||
|
||||
+ /* Configuration may have changed as a result of Match */
|
||||
+ if (options.num_auth_methods != 0)
|
||||
+ fatal("AuthenticationMethods is not supported with SSH "
|
||||
+ "protocol 1");
|
||||
+
|
||||
setproctitle("%s%s", authctxt->valid ? user : "unknown",
|
||||
use_privsep ? " [net]" : "");
|
||||
|
||||
diff --git a/auth2-chall.c b/auth2-chall.c
|
||||
index e6dbffe..5f7ec6d 100644
|
||||
--- a/auth2-chall.c
|
||||
+++ b/auth2-chall.c
|
||||
@@ -283,7 +283,7 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
|
||||
KbdintAuthctxt *kbdintctxt;
|
||||
int authenticated = 0, res;
|
||||
u_int i, nresp;
|
||||
- char **response = NULL, *method;
|
||||
+ char *devicename = NULL, **response = NULL;
|
||||
|
||||
if (authctxt == NULL)
|
||||
fatal("input_userauth_info_response: no authctxt");
|
||||
@@ -329,9 +329,7 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
|
||||
/* Failure! */
|
||||
break;
|
||||
}
|
||||
-
|
||||
- xasprintf(&method, "keyboard-interactive/%s", kbdintctxt->device->name);
|
||||
-
|
||||
+ devicename = kbdintctxt->device->name;
|
||||
if (!authctxt->postponed) {
|
||||
if (authenticated) {
|
||||
auth2_challenge_stop(authctxt);
|
||||
@@ -341,8 +339,8 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
|
||||
auth2_challenge_start(authctxt);
|
||||
}
|
||||
}
|
||||
- userauth_finish(authctxt, authenticated, method);
|
||||
- xfree(method);
|
||||
+ userauth_finish(authctxt, authenticated, "keyboard-interactive",
|
||||
+ devicename);
|
||||
}
|
||||
|
||||
void
|
||||
diff --git a/auth2-gss.c b/auth2-gss.c
|
||||
index 0d59b21..338c748 100644
|
||||
--- a/auth2-gss.c
|
||||
+++ b/auth2-gss.c
|
||||
@@ -163,7 +163,7 @@ input_gssapi_token(int type, u_int32_t plen, void *ctxt)
|
||||
}
|
||||
authctxt->postponed = 0;
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
|
||||
- userauth_finish(authctxt, 0, "gssapi-with-mic");
|
||||
+ userauth_finish(authctxt, 0, "gssapi-with-mic", NULL);
|
||||
} else {
|
||||
if (send_tok.length != 0) {
|
||||
packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
|
||||
@@ -251,7 +251,7 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
|
||||
- userauth_finish(authctxt, authenticated, "gssapi-with-mic");
|
||||
+ userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -291,7 +291,7 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, NULL);
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_MIC, NULL);
|
||||
dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
|
||||
- userauth_finish(authctxt, authenticated, "gssapi-with-mic");
|
||||
+ userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
|
||||
}
|
||||
|
||||
Authmethod method_gssapi = {
|
||||
diff --git a/auth2-jpake.c b/auth2-jpake.c
|
||||
index a460e82..e4ba9aa 100644
|
||||
--- a/auth2-jpake.c
|
||||
+++ b/auth2-jpake.c
|
||||
@@ -556,7 +556,7 @@ input_userauth_jpake_client_confirm(int type, u_int32_t seq, void *ctxt)
|
||||
authctxt->postponed = 0;
|
||||
jpake_free(authctxt->jpake_ctx);
|
||||
authctxt->jpake_ctx = NULL;
|
||||
- userauth_finish(authctxt, authenticated, method_jpake.name);
|
||||
+ userauth_finish(authctxt, authenticated, method_jpake.name, NULL);
|
||||
}
|
||||
|
||||
#endif /* JPAKE */
|
||||
diff --git a/auth2.c b/auth2.c
|
||||
index b66bef6..ea0fd92 100644
|
||||
--- a/auth2.c
|
||||
+++ b/auth2.c
|
||||
@@ -96,8 +96,10 @@ static void input_service_request(int, u_int32_t, void *);
|
||||
static void input_userauth_request(int, u_int32_t, void *);
|
||||
|
||||
/* helper */
|
||||
-static Authmethod *authmethod_lookup(const char *);
|
||||
-static char *authmethods_get(void);
|
||||
+static Authmethod *authmethod_lookup(Authctxt *, const char *);
|
||||
+static char *authmethods_get(Authctxt *authctxt);
|
||||
+static int method_allowed(Authctxt *, const char *);
|
||||
+static int list_starts_with(const char *, const char *);
|
||||
|
||||
char *
|
||||
auth2_read_banner(void)
|
||||
@@ -255,6 +257,8 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
|
||||
if (use_privsep)
|
||||
mm_inform_authserv(service, style);
|
||||
userauth_banner();
|
||||
+ if (auth2_setup_methods_lists(authctxt) != 0)
|
||||
+ packet_disconnect("no authentication methods enabled");
|
||||
} else if (strcmp(user, authctxt->user) != 0 ||
|
||||
strcmp(service, authctxt->service) != 0) {
|
||||
packet_disconnect("Change of username or service not allowed: "
|
||||
@@ -277,12 +281,12 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
|
||||
authctxt->server_caused_failure = 0;
|
||||
|
||||
/* try to authenticate user */
|
||||
- m = authmethod_lookup(method);
|
||||
+ m = authmethod_lookup(authctxt, method);
|
||||
if (m != NULL && authctxt->failures < options.max_authtries) {
|
||||
debug2("input_userauth_request: try method %s", method);
|
||||
authenticated = m->userauth(authctxt);
|
||||
}
|
||||
- userauth_finish(authctxt, authenticated, method);
|
||||
+ userauth_finish(authctxt, authenticated, method, NULL);
|
||||
|
||||
xfree(service);
|
||||
xfree(user);
|
||||
@@ -290,13 +294,17 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
|
||||
}
|
||||
|
||||
void
|
||||
-userauth_finish(Authctxt *authctxt, int authenticated, char *method)
|
||||
+userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
|
||||
+ const char *submethod)
|
||||
{
|
||||
char *methods;
|
||||
+ int partial = 0;
|
||||
|
||||
if (!authctxt->valid && authenticated)
|
||||
fatal("INTERNAL ERROR: authenticated invalid user %s",
|
||||
authctxt->user);
|
||||
+ if (authenticated && authctxt->postponed)
|
||||
+ fatal("INTERNAL ERROR: authenticated and postponed");
|
||||
|
||||
/* Special handling for root */
|
||||
if (authenticated && authctxt->pw->pw_uid == 0 &&
|
||||
@@ -307,6 +315,19 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
|
||||
#endif
|
||||
}
|
||||
|
||||
+ if (authenticated && options.num_auth_methods != 0) {
|
||||
+ if (!auth2_update_methods_lists(authctxt, method)) {
|
||||
+ authenticated = 0;
|
||||
+ partial = 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Log before sending the reply */
|
||||
+ auth_log(authctxt, authenticated, partial, method, submethod, " ssh2");
|
||||
+
|
||||
+ if (authctxt->postponed)
|
||||
+ return;
|
||||
+
|
||||
#ifdef USE_PAM
|
||||
if (options.use_pam && authenticated) {
|
||||
if (!PRIVSEP(do_pam_account())) {
|
||||
@@ -325,17 +346,10 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
|
||||
#ifdef _UNICOS
|
||||
if (authenticated && cray_access_denied(authctxt->user)) {
|
||||
authenticated = 0;
|
||||
- fatal("Access denied for user %s.",authctxt->user);
|
||||
+ fatal("Access denied for user %s.", authctxt->user);
|
||||
}
|
||||
#endif /* _UNICOS */
|
||||
|
||||
- /* Log before sending the reply */
|
||||
- auth_log(authctxt, authenticated, method, " ssh2");
|
||||
-
|
||||
- if (authctxt->postponed)
|
||||
- return;
|
||||
-
|
||||
- /* XXX todo: check if multiple auth methods are needed */
|
||||
if (authenticated == 1) {
|
||||
/* turn off userauth */
|
||||
dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
|
||||
@@ -348,7 +362,8 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
|
||||
|
||||
/* Allow initial try of "none" auth without failure penalty */
|
||||
if (!authctxt->server_caused_failure &&
|
||||
- (authctxt->attempt > 1 || strcmp(method, "none") != 0))
|
||||
+ (authctxt->attempt > 1 || strcmp(method, "none") != 0) &&
|
||||
+ partial == 0)
|
||||
authctxt->failures++;
|
||||
if (authctxt->failures >= options.max_authtries) {
|
||||
#ifdef SSH_AUDIT_EVENTS
|
||||
@@ -356,34 +371,61 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
|
||||
#endif
|
||||
packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
|
||||
}
|
||||
- methods = authmethods_get();
|
||||
+ methods = authmethods_get(authctxt);
|
||||
+ debug3("%s: failure partial=%d next methods=\"%s\"", __func__,
|
||||
+ partial, methods);
|
||||
packet_start(SSH2_MSG_USERAUTH_FAILURE);
|
||||
packet_put_cstring(methods);
|
||||
- packet_put_char(0); /* XXX partial success, unused */
|
||||
+ packet_put_char(partial);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
xfree(methods);
|
||||
}
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Checks whether method is allowed by at least one AuthenticationMethods
|
||||
+ * methods list. Returns 1 if allowed, or no methods lists configured.
|
||||
+ * 0 otherwise.
|
||||
+ */
|
||||
+static int
|
||||
+method_allowed(Authctxt *authctxt, const char *method)
|
||||
+{
|
||||
+ u_int i;
|
||||
+
|
||||
+ /*
|
||||
+ * NB. authctxt->num_auth_methods might be zero as a result of
|
||||
+ * auth2_setup_methods_lists(), so check the configuration.
|
||||
+ */
|
||||
+ if (options.num_auth_methods == 0)
|
||||
+ return 1;
|
||||
+ for (i = 0; i < authctxt->num_auth_methods; i++) {
|
||||
+ if (list_starts_with(authctxt->auth_methods[i], method))
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static char *
|
||||
-authmethods_get(void)
|
||||
+authmethods_get(Authctxt *authctxt)
|
||||
{
|
||||
Buffer b;
|
||||
char *list;
|
||||
- int i;
|
||||
+ u_int i;
|
||||
|
||||
buffer_init(&b);
|
||||
for (i = 0; authmethods[i] != NULL; i++) {
|
||||
if (strcmp(authmethods[i]->name, "none") == 0)
|
||||
continue;
|
||||
- if (authmethods[i]->enabled != NULL &&
|
||||
- *(authmethods[i]->enabled) != 0) {
|
||||
- if (buffer_len(&b) > 0)
|
||||
- buffer_append(&b, ",", 1);
|
||||
- buffer_append(&b, authmethods[i]->name,
|
||||
- strlen(authmethods[i]->name));
|
||||
- }
|
||||
+ if (authmethods[i]->enabled == NULL ||
|
||||
+ *(authmethods[i]->enabled) == 0)
|
||||
+ continue;
|
||||
+ if (!method_allowed(authctxt, authmethods[i]->name))
|
||||
+ continue;
|
||||
+ if (buffer_len(&b) > 0)
|
||||
+ buffer_append(&b, ",", 1);
|
||||
+ buffer_append(&b, authmethods[i]->name,
|
||||
+ strlen(authmethods[i]->name));
|
||||
}
|
||||
buffer_append(&b, "\0", 1);
|
||||
list = xstrdup(buffer_ptr(&b));
|
||||
@@ -392,7 +434,7 @@ authmethods_get(void)
|
||||
}
|
||||
|
||||
static Authmethod *
|
||||
-authmethod_lookup(const char *name)
|
||||
+authmethod_lookup(Authctxt *authctxt, const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -400,10 +442,152 @@ authmethod_lookup(const char *name)
|
||||
for (i = 0; authmethods[i] != NULL; i++)
|
||||
if (authmethods[i]->enabled != NULL &&
|
||||
*(authmethods[i]->enabled) != 0 &&
|
||||
- strcmp(name, authmethods[i]->name) == 0)
|
||||
+ strcmp(name, authmethods[i]->name) == 0 &&
|
||||
+ method_allowed(authctxt, authmethods[i]->name))
|
||||
return authmethods[i];
|
||||
debug2("Unrecognized authentication method name: %s",
|
||||
name ? name : "NULL");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Check a comma-separated list of methods for validity. Is need_enable is
|
||||
+ * non-zero, then also require that the methods are enabled.
|
||||
+ * Returns 0 on success or -1 if the methods list is invalid.
|
||||
+ */
|
||||
+int
|
||||
+auth2_methods_valid(const char *_methods, int need_enable)
|
||||
+{
|
||||
+ char *methods, *omethods, *method;
|
||||
+ u_int i, found;
|
||||
+ int ret = -1;
|
||||
+
|
||||
+ if (*_methods == '\0') {
|
||||
+ error("empty authentication method list");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ omethods = methods = xstrdup(_methods);
|
||||
+ while ((method = strsep(&methods, ",")) != NULL) {
|
||||
+ for (found = i = 0; !found && authmethods[i] != NULL; i++) {
|
||||
+ if (strcmp(method, authmethods[i]->name) != 0)
|
||||
+ continue;
|
||||
+ if (need_enable) {
|
||||
+ if (authmethods[i]->enabled == NULL ||
|
||||
+ *(authmethods[i]->enabled) == 0) {
|
||||
+ error("Disabled method \"%s\" in "
|
||||
+ "AuthenticationMethods list \"%s\"",
|
||||
+ method, _methods);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+ found = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ if (!found) {
|
||||
+ error("Unknown authentication method \"%s\" in list",
|
||||
+ method);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+ ret = 0;
|
||||
+ out:
|
||||
+ free(omethods);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Prune the AuthenticationMethods supplied in the configuration, removing
|
||||
+ * any methods lists that include disabled methods. Note that this might
|
||||
+ * leave authctxt->num_auth_methods == 0, even when multiple required auth
|
||||
+ * has been requested. For this reason, all tests for whether multiple is
|
||||
+ * enabled should consult options.num_auth_methods directly.
|
||||
+ */
|
||||
+int
|
||||
+auth2_setup_methods_lists(Authctxt *authctxt)
|
||||
+{
|
||||
+ u_int i;
|
||||
+
|
||||
+ if (options.num_auth_methods == 0)
|
||||
+ return 0;
|
||||
+ debug3("%s: checking methods", __func__);
|
||||
+ authctxt->auth_methods = xcalloc(options.num_auth_methods,
|
||||
+ sizeof(*authctxt->auth_methods));
|
||||
+ authctxt->num_auth_methods = 0;
|
||||
+ for (i = 0; i < options.num_auth_methods; i++) {
|
||||
+ if (auth2_methods_valid(options.auth_methods[i], 1) != 0) {
|
||||
+ logit("Authentication methods list \"%s\" contains "
|
||||
+ "disabled method, skipping",
|
||||
+ options.auth_methods[i]);
|
||||
+ continue;
|
||||
+ }
|
||||
+ debug("authentication methods list %d: %s",
|
||||
+ authctxt->num_auth_methods, options.auth_methods[i]);
|
||||
+ authctxt->auth_methods[authctxt->num_auth_methods++] =
|
||||
+ xstrdup(options.auth_methods[i]);
|
||||
+ }
|
||||
+ if (authctxt->num_auth_methods == 0) {
|
||||
+ error("No AuthenticationMethods left after eliminating "
|
||||
+ "disabled methods");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+list_starts_with(const char *methods, const char *method)
|
||||
+{
|
||||
+ size_t l = strlen(method);
|
||||
+
|
||||
+ if (strncmp(methods, method, l) != 0)
|
||||
+ return 0;
|
||||
+ if (methods[l] != ',' && methods[l] != '\0')
|
||||
+ return 0;
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Remove method from the start of a comma-separated list of methods.
|
||||
+ * Returns 0 if the list of methods did not start with that method or 1
|
||||
+ * if it did.
|
||||
+ */
|
||||
+static int
|
||||
+remove_method(char **methods, const char *method)
|
||||
+{
|
||||
+ char *omethods = *methods;
|
||||
+ size_t l = strlen(method);
|
||||
+
|
||||
+ if (!list_starts_with(omethods, method))
|
||||
+ return 0;
|
||||
+ *methods = xstrdup(omethods + l + (omethods[l] == ',' ? 1 : 0));
|
||||
+ free(omethods);
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Called after successful authentication. Will remove the successful method
|
||||
+ * from the start of each list in which it occurs. If it was the last method
|
||||
+ * in any list, then authentication is deemed successful.
|
||||
+ * Returns 1 if the method completed any authentication list or 0 otherwise.
|
||||
+ */
|
||||
+int
|
||||
+auth2_update_methods_lists(Authctxt *authctxt, const char *method)
|
||||
+{
|
||||
+ u_int i, found = 0;
|
||||
+
|
||||
+ debug3("%s: updating methods list after \"%s\"", __func__, method);
|
||||
+ for (i = 0; i < authctxt->num_auth_methods; i++) {
|
||||
+ if (!remove_method(&(authctxt->auth_methods[i]), method))
|
||||
+ continue;
|
||||
+ found = 1;
|
||||
+ if (*authctxt->auth_methods[i] == '\0') {
|
||||
+ debug2("authentication methods list %d complete", i);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ debug3("authentication methods list %d remaining: \"%s\"",
|
||||
+ i, authctxt->auth_methods[i]);
|
||||
+ }
|
||||
+ /* This should not happen, but would be bad if it did */
|
||||
+ if (!found)
|
||||
+ fatal("%s: method not in AuthenticationMethods", __func__);
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/monitor.c b/monitor.c
|
||||
index 1dc42f5..66f3eea 100644
|
||||
--- a/monitor.c
|
||||
+++ b/monitor.c
|
||||
@@ -199,6 +199,7 @@ static int key_blobtype = MM_NOKEY;
|
||||
static char *hostbased_cuser = NULL;
|
||||
static char *hostbased_chost = NULL;
|
||||
static char *auth_method = "unknown";
|
||||
+static char *auth_submethod = NULL;
|
||||
static u_int session_id2_len = 0;
|
||||
static u_char *session_id2 = NULL;
|
||||
static pid_t monitor_child_pid;
|
||||
@@ -352,7 +353,7 @@ void
|
||||
monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
|
||||
{
|
||||
struct mon_table *ent;
|
||||
- int authenticated = 0;
|
||||
+ int authenticated = 0, partial = 0;
|
||||
|
||||
debug3("preauth child monitor started");
|
||||
|
||||
@@ -379,8 +380,26 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
|
||||
|
||||
/* The first few requests do not require asynchronous access */
|
||||
while (!authenticated) {
|
||||
+ partial = 0;
|
||||
auth_method = "unknown";
|
||||
+ auth_submethod = NULL;
|
||||
authenticated = (monitor_read(pmonitor, mon_dispatch, &ent) == 1);
|
||||
+
|
||||
+ /* Special handling for multiple required authentications */
|
||||
+ if (options.num_auth_methods != 0) {
|
||||
+ if (!compat20)
|
||||
+ fatal("AuthenticationMethods is not supported"
|
||||
+ "with SSH protocol 1");
|
||||
+ if (authenticated &&
|
||||
+ !auth2_update_methods_lists(authctxt,
|
||||
+ auth_method)) {
|
||||
+ debug3("%s: method %s: partial", __func__,
|
||||
+ auth_method);
|
||||
+ authenticated = 0;
|
||||
+ partial = 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (authenticated) {
|
||||
if (!(ent->flags & MON_AUTHDECIDE))
|
||||
fatal("%s: unexpected authentication from %d",
|
||||
@@ -403,9 +422,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
|
||||
}
|
||||
|
||||
if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) {
|
||||
- auth_log(authctxt, authenticated, auth_method,
|
||||
+ auth_log(authctxt, authenticated, partial,
|
||||
+ auth_method, auth_submethod,
|
||||
compat20 ? " ssh2" : "");
|
||||
- if (!authenticated)
|
||||
+ if (!authenticated && !partial)
|
||||
authctxt->failures++;
|
||||
}
|
||||
#ifdef JPAKE
|
||||
@@ -781,7 +801,17 @@ mm_answer_pwnamallow(int sock, Buffer *m)
|
||||
COPY_MATCH_STRING_OPTS();
|
||||
#undef M_CP_STROPT
|
||||
#undef M_CP_STRARRAYOPT
|
||||
-
|
||||
+
|
||||
+ /* Create valid auth method lists */
|
||||
+ if (compat20 && auth2_setup_methods_lists(authctxt) != 0) {
|
||||
+ /*
|
||||
+ * The monitor will continue long enough to let the child
|
||||
+ * run to it's packet_disconnect(), but it must not allow any
|
||||
+ * authentication to succeed.
|
||||
+ */
|
||||
+ debug("%s: no valid authentication method lists", __func__);
|
||||
+ }
|
||||
+
|
||||
debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
|
||||
mm_request_send(sock, MONITOR_ANS_PWNAM, m);
|
||||
|
||||
@@ -918,7 +948,11 @@ mm_answer_bsdauthrespond(int sock, Buffer *m)
|
||||
debug3("%s: sending authenticated: %d", __func__, authok);
|
||||
mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m);
|
||||
|
||||
- auth_method = "bsdauth";
|
||||
+ if (compat20)
|
||||
+ auth_method = "keyboard-interactive"; /* XXX auth_submethod */
|
||||
+ else
|
||||
+ auth_method = "bsdauth";
|
||||
+
|
||||
|
||||
return (authok != 0);
|
||||
}
|
||||
@@ -1057,7 +1091,9 @@ mm_answer_pam_query(int sock, Buffer *m)
|
||||
xfree(prompts);
|
||||
if (echo_on != NULL)
|
||||
xfree(echo_on);
|
||||
- auth_method = "keyboard-interactive/pam";
|
||||
+ auth_method = "keyboard-interactive";
|
||||
+ auth_submethod = "pam";
|
||||
+
|
||||
mm_request_send(sock, MONITOR_ANS_PAM_QUERY, m);
|
||||
return (0);
|
||||
}
|
||||
@@ -1086,7 +1122,8 @@ mm_answer_pam_respond(int sock, Buffer *m)
|
||||
buffer_clear(m);
|
||||
buffer_put_int(m, ret);
|
||||
mm_request_send(sock, MONITOR_ANS_PAM_RESPOND, m);
|
||||
- auth_method = "keyboard-interactive/pam";
|
||||
+ auth_method = "keyboard-interactive";
|
||||
+ auth_submethod= "pam";
|
||||
if (ret == 0)
|
||||
sshpam_authok = sshpam_ctxt;
|
||||
return (0);
|
||||
@@ -1100,7 +1137,8 @@ mm_answer_pam_free_ctx(int sock, Buffer *m)
|
||||
(sshpam_device.free_ctx)(sshpam_ctxt);
|
||||
buffer_clear(m);
|
||||
mm_request_send(sock, MONITOR_ANS_PAM_FREE_CTX, m);
|
||||
- auth_method = "keyboard-interactive/pam";
|
||||
+ auth_method = "keyboard-interactive";
|
||||
+ auth_submethod = "pam";
|
||||
return (sshpam_authok == sshpam_ctxt);
|
||||
}
|
||||
#endif
|
||||
@@ -1178,7 +1216,8 @@ mm_answer_keyallowed(int sock, Buffer *m)
|
||||
hostbased_chost = chost;
|
||||
} else {
|
||||
/* Log failed attempt */
|
||||
- auth_log(authctxt, 0, auth_method, compat20 ? " ssh2" : "");
|
||||
+ auth_log(authctxt, 0, 0, auth_method, NULL,
|
||||
+ compat20 ? " ssh2" : "");
|
||||
xfree(blob);
|
||||
xfree(cuser);
|
||||
xfree(chost);
|
||||
diff --git a/servconf.c b/servconf.c
|
||||
index 906778f..2c84993 100644
|
||||
--- a/servconf.c
|
||||
+++ b/servconf.c
|
||||
@@ -48,6 +48,8 @@
|
||||
#include "groupaccess.h"
|
||||
#include "canohost.h"
|
||||
#include "packet.h"
|
||||
+#include "hostfile.h"
|
||||
+#include "auth.h"
|
||||
|
||||
static void add_listen_addr(ServerOptions *, char *, int);
|
||||
static void add_one_listen_addr(ServerOptions *, char *, int);
|
||||
@@ -329,6 +331,7 @@ typedef enum {
|
||||
sZeroKnowledgePasswordAuthentication, sHostCertificate,
|
||||
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
|
||||
sKexAlgorithms, sIPQoS, sVersionAddendum,
|
||||
+ sAuthenticationMethods,
|
||||
sDeprecated, sUnsupported
|
||||
} ServerOpCodes;
|
||||
|
||||
@@ -454,6 +457,7 @@ static struct {
|
||||
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
|
||||
{ "ipqos", sIPQoS, SSHCFG_ALL },
|
||||
{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
|
||||
+ { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
|
||||
{ NULL, sBadOption, 0 }
|
||||
};
|
||||
|
||||
@@ -1498,6 +1502,24 @@ process_server_config_line(ServerOptions *options, char *line,
|
||||
}
|
||||
return 0;
|
||||
|
||||
+ case sAuthenticationMethods:
|
||||
+ if (*activep && options->num_auth_methods == 0) {
|
||||
+ while ((arg = strdelim(&cp)) && *arg != '\0') {
|
||||
+ if (options->num_auth_methods >=
|
||||
+ MAX_AUTH_METHODS)
|
||||
+ fatal("%s line %d: "
|
||||
+ "too many authentication methods.",
|
||||
+ filename, linenum);
|
||||
+ if (auth2_methods_valid(arg, 0) != 0)
|
||||
+ fatal("%s line %d: invalid "
|
||||
+ "authentication method list.",
|
||||
+ filename, linenum);
|
||||
+ options->auth_methods[
|
||||
+ options->num_auth_methods++] = xstrdup(arg);
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+
|
||||
case sDeprecated:
|
||||
logit("%s line %d: Deprecated option %s",
|
||||
filename, linenum, arg);
|
||||
@@ -1925,6 +1947,8 @@ dump_config(ServerOptions *o)
|
||||
dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
|
||||
dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
|
||||
dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
|
||||
+ dump_cfg_strarray_oneline(sAuthenticationMethods,
|
||||
+ o->num_auth_methods, o->auth_methods);
|
||||
|
||||
/* other arguments */
|
||||
for (i = 0; i < o->num_subsystems; i++)
|
||||
diff --git a/servconf.h b/servconf.h
|
||||
index 096d596..ef80eef 100644
|
||||
--- a/servconf.h
|
||||
+++ b/servconf.h
|
||||
@@ -28,6 +28,7 @@
|
||||
#define MAX_ACCEPT_ENV 256 /* Max # of env vars. */
|
||||
#define MAX_MATCH_GROUPS 256 /* Max # of groups for Match. */
|
||||
#define MAX_AUTHKEYS_FILES 256 /* Max # of authorized_keys files. */
|
||||
+#define MAX_AUTH_METHODS 256 /* Max # of AuthenticationMethods. */
|
||||
|
||||
/* permit_root_login */
|
||||
#define PERMIT_NOT_SET -1
|
||||
@@ -168,6 +169,9 @@ typedef struct {
|
||||
char *authorized_principals_file;
|
||||
|
||||
char *version_addendum; /* Appended to SSH banner */
|
||||
+
|
||||
+ u_int num_auth_methods;
|
||||
+ char *auth_methods[MAX_AUTH_METHODS];
|
||||
} ServerOptions;
|
||||
|
||||
/* Information about the incoming connection as used by Match */
|
||||
@@ -197,6 +201,7 @@ struct connection_info {
|
||||
M_CP_STRARRAYOPT(allow_groups, num_allow_groups); \
|
||||
M_CP_STRARRAYOPT(deny_groups, num_deny_groups); \
|
||||
M_CP_STRARRAYOPT(accept_env, num_accept_env); \
|
||||
+ M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \
|
||||
} while (0)
|
||||
|
||||
struct connection_info *get_connection_info(int, int);
|
||||
diff --git a/sshd.c b/sshd.c
|
||||
index d5ec4e6..cb4bdd3 100644
|
||||
--- a/sshd.c
|
||||
+++ b/sshd.c
|
||||
@@ -1333,6 +1333,7 @@ main(int ac, char **av)
|
||||
int remote_port;
|
||||
char *line;
|
||||
int config_s[2] = { -1 , -1 };
|
||||
+ u_int n;
|
||||
u_int64_t ibytes, obytes;
|
||||
mode_t new_umask;
|
||||
Key *key;
|
||||
@@ -1555,6 +1556,26 @@ main(int ac, char **av)
|
||||
if (options.challenge_response_authentication)
|
||||
options.kbd_interactive_authentication = 1;
|
||||
|
||||
+ /*
|
||||
+ * Check whether there is any path through configured auth methods.
|
||||
+ * Unfortunately it is not possible to verify this generally before
|
||||
+ * daemonisation in the presence of Match block, but this catches
|
||||
+ * and warns for trivial misconfigurations that could break login.
|
||||
+ */
|
||||
+ if (options.num_auth_methods != 0) {
|
||||
+ if ((options.protocol & SSH_PROTO_1))
|
||||
+ fatal("AuthenticationMethods is not supported with "
|
||||
+ "SSH protocol 1");
|
||||
+ for (n = 0; n < options.num_auth_methods; n++) {
|
||||
+ if (auth2_methods_valid(options.auth_methods[n],
|
||||
+ 1) == 0)
|
||||
+ break;
|
||||
+ }
|
||||
+ if (n >= options.num_auth_methods)
|
||||
+ fatal("AuthenticationMethods cannot be satisfied by "
|
||||
+ "enabled authentication methods");
|
||||
+ }
|
||||
+
|
||||
/* set default channel AF */
|
||||
channel_set_af(options.address_family);
|
||||
|
||||
diff --git a/sshd_config.5 b/sshd_config.5
|
||||
index 314ecfb..ed81ac8 100644
|
||||
--- a/sshd_config.5
|
||||
+++ b/sshd_config.5
|
||||
@@ -151,6 +151,28 @@ See
|
||||
in
|
||||
.Xr ssh_config 5
|
||||
for more information on patterns.
|
||||
+.It Cm AuthenticationMethods
|
||||
+Specifies the authentication methods that must be successfully completed
|
||||
+for a user to be granted access.
|
||||
+This option must be followed by one or more comma-separated lists of
|
||||
+authentication method names.
|
||||
+Successful authentication requires completion of every method in at least
|
||||
+one of these lists.
|
||||
+.Pp
|
||||
+For example, an argument of
|
||||
+.Dq publickey,password publickey,keyboard-interactive
|
||||
+would require the user to complete public key authentication, followed by
|
||||
+either password or keyboard interactive authentication.
|
||||
+Only methods that are next in one or more lists are offered at each stage,
|
||||
+so for this example, it would not be possible to attempt password or
|
||||
+keyboard-interactive authentication before public key.
|
||||
+.Pp
|
||||
+This option is only available for SSH protocol 2 and will yield a fatal
|
||||
+error if enabled if protocol 1 is also enabled.
|
||||
+Note that each authentication method listed should also be explicitly enabled
|
||||
+in the configuration.
|
||||
+The default is not to require multiple authentication; successful completion
|
||||
+of a single authentication method is sufficient.
|
||||
.It Cm AuthorizedKeysFile
|
||||
Specifies the file that contains the public keys that can be used
|
||||
for user authentication.
|
||||
@@ -711,6 +733,7 @@ Available keywords are
|
||||
.Cm AllowGroups ,
|
||||
.Cm AllowTcpForwarding ,
|
||||
.Cm AllowUsers ,
|
||||
+.Cm AuthenticationMethods ,
|
||||
.Cm AuthorizedKeysFile ,
|
||||
.Cm AuthorizedPrincipalsFile ,
|
||||
.Cm Banner ,
|
@ -1,45 +0,0 @@
|
||||
diff --git a/servconf.c b/servconf.c
|
||||
index 684fbb4..a230c7b 100644
|
||||
--- a/servconf.c
|
||||
+++ b/servconf.c
|
||||
@@ -267,11 +267,11 @@ fill_default_server_options(ServerOptions *options)
|
||||
if (options->gateway_ports == -1)
|
||||
options->gateway_ports = 0;
|
||||
if (options->max_startups == -1)
|
||||
- options->max_startups = 10;
|
||||
+ options->max_startups = 100;
|
||||
if (options->max_startups_rate == -1)
|
||||
- options->max_startups_rate = 100; /* 100% */
|
||||
+ options->max_startups_rate = 30; /* 30% */
|
||||
if (options->max_startups_begin == -1)
|
||||
- options->max_startups_begin = options->max_startups;
|
||||
+ options->max_startups_begin = 10;
|
||||
if (options->max_authtries == -1)
|
||||
options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
|
||||
if (options->max_sessions == -1)
|
||||
diff --git a/sshd_config b/sshd_config
|
||||
index d1b85d0..5c03fd9 100644
|
||||
--- a/sshd_config
|
||||
+++ b/sshd_config
|
||||
@@ -126,7 +126,7 @@ UsePrivilegeSeparation sandbox # Default for new installations.
|
||||
#ShowPatchLevel no
|
||||
#UseDNS yes
|
||||
#PidFile /var/run/sshd.pid
|
||||
-#MaxStartups 10
|
||||
+#MaxStartups 10:30:100
|
||||
#PermitTunnel no
|
||||
#ChrootDirectory none
|
||||
#VersionAddendum none
|
||||
diff --git a/sshd_config.5 b/sshd_config.5
|
||||
index fd0d35a..f02f6cc 100644
|
||||
--- a/sshd_config.5
|
||||
+++ b/sshd_config.5
|
||||
@@ -826,7 +826,7 @@ SSH daemon.
|
||||
Additional connections will be dropped until authentication succeeds or the
|
||||
.Cm LoginGraceTime
|
||||
expires for a connection.
|
||||
-The default is 10.
|
||||
+The default is 10:30:100.
|
||||
.Pp
|
||||
Alternatively, random early drop can be enabled by specifying
|
||||
the three colon separated values
|
@ -1,24 +0,0 @@
|
||||
diff -up openssh-6.1p1/moduli.0.man-moduli openssh-6.1p1/moduli.0
|
||||
--- openssh-6.1p1/moduli.0.man-moduli 2012-11-06 09:42:13.677062887 +0100
|
||||
+++ openssh-6.1p1/moduli.0 2012-11-06 09:42:58.693543381 +0100
|
||||
@@ -25,7 +25,7 @@ DESCRIPTION
|
||||
|
||||
0 Unknown, not tested.
|
||||
2 "Safe" prime; (p-1)/2 is also prime.
|
||||
- 4 Sophie Germain; (p+1)*2 is also prime.
|
||||
+ 4 Sophie Germain; (p*2)+1 is also prime.
|
||||
|
||||
Moduli candidates initially produced by ssh-keygen(1)
|
||||
are Sophie Germain primes (type 4). Further primality
|
||||
diff -up openssh-6.1p1/moduli.5.man-moduli openssh-6.1p1/moduli.5
|
||||
--- openssh-6.1p1/moduli.5.man-moduli 2012-11-06 09:42:17.730035388 +0100
|
||||
+++ openssh-6.1p1/moduli.5 2012-11-06 09:43:31.403180375 +0100
|
||||
@@ -61,7 +61,7 @@ Unknown, not tested.
|
||||
.It 2
|
||||
"Safe" prime; (p-1)/2 is also prime.
|
||||
.It 4
|
||||
-Sophie Germain; (p+1)*2 is also prime.
|
||||
+Sophie Germain; (p*2)+1 is also prime.
|
||||
.El
|
||||
.Pp
|
||||
Moduli candidates initially produced by
|
@ -1,22 +0,0 @@
|
||||
diff -up openssh-6.1p1/servconf.c.required-authentication openssh-6.1p1/servconf.c
|
||||
--- openssh-6.1p1/servconf.c.required-authentication 2012-11-30 21:13:14.375382453 +0100
|
||||
+++ openssh-6.1p1/servconf.c 2012-11-30 21:33:56.972017545 +0100
|
||||
@@ -495,6 +495,8 @@ static struct {
|
||||
{ "authorizedkeyscommandrunas", sAuthorizedKeysCommandUser, SSHCFG_ALL },
|
||||
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
|
||||
{ "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
|
||||
+ { "requiredauthentications1", sAuthenticationMethods, SSHCFG_ALL },
|
||||
+ { "requiredauthentications2", sAuthenticationMethods, SSHCFG_ALL },
|
||||
{ NULL, sBadOption, 0 }
|
||||
};
|
||||
|
||||
@@ -1560,6 +1562,9 @@ process_server_config_line(ServerOptions
|
||||
return 0;
|
||||
|
||||
case sAuthenticationMethods:
|
||||
+ if (strncasecmp(arg, "requiredauthentications", 23) == 0)
|
||||
+ logit("%s line %d: Option %s is obsolete. Please use AuthenticationMethods",
|
||||
+ filename, linenum, arg);
|
||||
if (*activep && options->num_auth_methods == 0) {
|
||||
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
||||
if (options->num_auth_methods >=
|
@ -1,644 +0,0 @@
|
||||
diff -up openssh-6.2p1/audit-bsm.c.audit1 openssh-6.2p1/audit-bsm.c
|
||||
--- openssh-6.2p1/audit-bsm.c.audit1 2012-02-24 00:40:43.000000000 +0100
|
||||
+++ openssh-6.2p1/audit-bsm.c 2013-03-25 17:18:30.934758118 +0100
|
||||
@@ -375,10 +375,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-6.2p1/audit.c.audit1 openssh-6.2p1/audit.c
|
||||
--- openssh-6.2p1/audit.c.audit1 2011-01-17 11:15:30.000000000 +0100
|
||||
+++ openssh-6.2p1/audit.c 2013-03-25 17:18:30.934758118 +0100
|
||||
@@ -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-6.2p1/audit.h.audit1 openssh-6.2p1/audit.h
|
||||
--- openssh-6.2p1/audit.h.audit1 2011-01-17 11:15:30.000000000 +0100
|
||||
+++ openssh-6.2p1/audit.h 2013-03-25 17:18:30.934758118 +0100
|
||||
@@ -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-6.2p1/audit-linux.c.audit1 openssh-6.2p1/audit-linux.c
|
||||
--- openssh-6.2p1/audit-linux.c.audit1 2011-01-17 11:15:30.000000000 +0100
|
||||
+++ openssh-6.2p1/audit-linux.c 2013-03-25 17:18:30.934758118 +0100
|
||||
@@ -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-6.2p1/monitor.c.audit1 openssh-6.2p1/monitor.c
|
||||
--- openssh-6.2p1/monitor.c.audit1 2013-03-25 17:18:30.913757986 +0100
|
||||
+++ openssh-6.2p1/monitor.c 2013-03-25 17:18:30.935758124 +0100
|
||||
@@ -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 *);
|
||||
@@ -272,6 +273,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}
|
||||
};
|
||||
@@ -314,6 +316,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}
|
||||
};
|
||||
@@ -1433,6 +1436,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);
|
||||
}
|
||||
|
||||
@@ -1755,11 +1764,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-6.2p1/monitor.h.audit1 openssh-6.2p1/monitor.h
|
||||
--- openssh-6.2p1/monitor.h.audit1 2013-03-25 17:18:30.935758124 +0100
|
||||
+++ openssh-6.2p1/monitor.h 2013-03-25 17:24:53.474078078 +0100
|
||||
@@ -68,7 +68,9 @@ enum monitor_reqtype {
|
||||
MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107,
|
||||
MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109,
|
||||
MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111,
|
||||
- MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113,
|
||||
+ MONITOR_REQ_AUDIT_EVENT = 112,
|
||||
+ MONITOR_REQ_AUDIT_COMMAND = 114, MONITOR_ANS_AUDIT_COMMAND = 115,
|
||||
+ MONITOR_REQ_AUDIT_END_COMMAND = 116
|
||||
|
||||
};
|
||||
|
||||
diff -up openssh-6.2p1/monitor_wrap.c.audit1 openssh-6.2p1/monitor_wrap.c
|
||||
--- openssh-6.2p1/monitor_wrap.c.audit1 2013-03-25 17:18:30.913757986 +0100
|
||||
+++ openssh-6.2p1/monitor_wrap.c 2013-03-25 17:18:30.936758131 +0100
|
||||
@@ -1189,10 +1189,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);
|
||||
|
||||
@@ -1200,6 +1201,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-6.2p1/monitor_wrap.h.audit1 openssh-6.2p1/monitor_wrap.h
|
||||
--- openssh-6.2p1/monitor_wrap.h.audit1 2011-06-20 06:42:23.000000000 +0200
|
||||
+++ openssh-6.2p1/monitor_wrap.h 2013-03-25 17:18:30.936758131 +0100
|
||||
@@ -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-6.2p1/session.c.audit1 openssh-6.2p1/session.c
|
||||
--- openssh-6.2p1/session.c.audit1 2013-03-15 01:22:37.000000000 +0100
|
||||
+++ openssh-6.2p1/session.c 2013-03-25 17:18:30.937758137 +0100
|
||||
@@ -745,6 +745,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,
|
||||
@@ -816,15 +824,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);
|
||||
@@ -1856,6 +1868,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;
|
||||
}
|
||||
@@ -1938,6 +1951,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;
|
||||
@@ -2463,6 +2489,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)
|
||||
{
|
||||
@@ -2471,6 +2521,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)
|
||||
@@ -2690,6 +2744,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)
|
||||
{
|
||||
@@ -2738,5 +2801,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-6.2p1/session.h.audit1 openssh-6.2p1/session.h
|
||||
--- openssh-6.2p1/session.h.audit1 2008-05-19 07:34:50.000000000 +0200
|
||||
+++ openssh-6.2p1/session.h 2013-03-25 17:18:30.937758137 +0100
|
||||
@@ -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-6.2p1/sshd.c.audit1 openssh-6.2p1/sshd.c
|
||||
--- openssh-6.2p1/sshd.c.audit1 2013-03-25 17:18:30.919758024 +0100
|
||||
+++ openssh-6.2p1/sshd.c 2013-03-25 17:18:30.937758137 +0100
|
||||
@@ -2409,7 +2409,8 @@ cleanup_exit(int i)
|
||||
}
|
||||
#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);
|
@ -1,534 +0,0 @@
|
||||
diff -up openssh-6.2p1/audit-bsm.c.audit3 openssh-6.2p1/audit-bsm.c
|
||||
--- openssh-6.2p1/audit-bsm.c.audit3 2013-03-25 17:30:41.329102631 +0100
|
||||
+++ openssh-6.2p1/audit-bsm.c 2013-03-25 17:30:41.338102682 +0100
|
||||
@@ -473,4 +473,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-6.2p1/audit.c.audit3 openssh-6.2p1/audit.c
|
||||
--- openssh-6.2p1/audit.c.audit3 2013-03-25 17:30:41.330102636 +0100
|
||||
+++ openssh-6.2p1/audit.c 2013-03-25 17:30:41.339102688 +0100
|
||||
@@ -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-6.2p1/audit.h.audit3 openssh-6.2p1/audit.h
|
||||
--- openssh-6.2p1/audit.h.audit3 2013-03-25 17:30:41.330102636 +0100
|
||||
+++ openssh-6.2p1/audit.h 2013-03-25 17:30:41.339102688 +0100
|
||||
@@ -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-6.2p1/audit-linux.c.audit3 openssh-6.2p1/audit-linux.c
|
||||
--- openssh-6.2p1/audit-linux.c.audit3 2013-03-25 17:30:41.331102642 +0100
|
||||
+++ openssh-6.2p1/audit-linux.c 2013-03-25 17:30:41.339102688 +0100
|
||||
@@ -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,60 @@ 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" };
|
||||
+ char *s;
|
||||
+ int audit_fd;
|
||||
+
|
||||
+ snprintf(buf, sizeof(buf), "op=unsupported-%s direction=? cipher=? ksize=? rport=%d laddr=%s lport=%d ",
|
||||
+ name[what], get_remote_port(), (s = get_local_ipaddr(packet_get_connection_in())),
|
||||
+ get_local_port());
|
||||
+ xfree(s);
|
||||
+ 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);
|
||||
+ char *s;
|
||||
+
|
||||
+ 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(), (s = get_local_ipaddr(packet_get_connection_in())), get_local_port());
|
||||
+ xfree(s);
|
||||
+ 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-6.2p1/auditstub.c.audit3 openssh-6.2p1/auditstub.c
|
||||
--- openssh-6.2p1/auditstub.c.audit3 2013-03-25 17:30:41.340102694 +0100
|
||||
+++ openssh-6.2p1/auditstub.c 2013-03-25 17:30:41.340102694 +0100
|
||||
@@ -0,0 +1,39 @@
|
||||
+/* $Id: auditstub.c,v 1.1 jfch Exp $ */
|
||||
+
|
||||
+/*
|
||||
+ * Copyright 2010 Red Hat, Inc. All rights reserved.
|
||||
+ * Use is subject to license terms.
|
||||
+ *
|
||||
+ * Redistribution and use in source and binary forms, with or without
|
||||
+ * modification, are permitted provided that the following conditions
|
||||
+ * are met:
|
||||
+ * 1. Redistributions of source code must retain the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer.
|
||||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||||
+ * notice, this list of conditions and the following disclaimer in the
|
||||
+ * documentation and/or other materials provided with the distribution.
|
||||
+ *
|
||||
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+ *
|
||||
+ * Red Hat author: Jan F. Chadima <jchadima@redhat.com>
|
||||
+ */
|
||||
+
|
||||
+void
|
||||
+audit_unsupported(int n)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+audit_kex(int ctos, char *enc, char *mac, char *comp)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
diff -up openssh-6.2p1/cipher.c.audit3 openssh-6.2p1/cipher.c
|
||||
--- openssh-6.2p1/cipher.c.audit3 2013-03-25 17:30:41.340102694 +0100
|
||||
+++ openssh-6.2p1/cipher.c 2013-03-25 17:32:33.117743548 +0100
|
||||
@@ -58,17 +58,7 @@ extern const EVP_CIPHER *evp_ssh1_bf(voi
|
||||
extern const EVP_CIPHER *evp_ssh1_3des(void);
|
||||
extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
|
||||
|
||||
-struct Cipher {
|
||||
- char *name;
|
||||
- int number; /* for ssh1 only */
|
||||
- u_int block_size;
|
||||
- u_int key_len;
|
||||
- u_int iv_len; /* defaults to block_size */
|
||||
- u_int auth_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, 0, 0, EVP_enc_null },
|
||||
{ "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc },
|
||||
{ "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des },
|
||||
diff -up openssh-6.2p1/cipher.h.audit3 openssh-6.2p1/cipher.h
|
||||
--- openssh-6.2p1/cipher.h.audit3 2013-03-25 17:30:41.341102699 +0100
|
||||
+++ openssh-6.2p1/cipher.h 2013-03-25 17:32:45.338813408 +0100
|
||||
@@ -61,7 +61,18 @@
|
||||
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 iv_len; /* defaults to block_size */
|
||||
+ u_int auth_len;
|
||||
+ u_int discard_len;
|
||||
+ u_int cbc_mode;
|
||||
+ const EVP_CIPHER *(*evptype)(void);
|
||||
+};
|
||||
+
|
||||
struct CipherContext {
|
||||
int plaintext;
|
||||
int encrypt;
|
||||
diff -up openssh-6.2p1/kex.c.audit3 openssh-6.2p1/kex.c
|
||||
--- openssh-6.2p1/kex.c.audit3 2013-01-09 06:12:19.000000000 +0100
|
||||
+++ openssh-6.2p1/kex.c 2013-03-25 17:33:40.352129450 +0100
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "dispatch.h"
|
||||
#include "monitor.h"
|
||||
#include "roaming.h"
|
||||
+#include "audit.h"
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
|
||||
# if defined(HAVE_EVP_SHA256)
|
||||
@@ -296,9 +297,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;
|
||||
@@ -314,9 +319,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 */
|
||||
@@ -331,8 +340,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) {
|
||||
@@ -460,6 +473,9 @@ kex_choose_conf(Kex *kex)
|
||||
newkeys->enc.name,
|
||||
authlen == 0 ? newkeys->mac.name : "<implicit>",
|
||||
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-6.2p1/Makefile.in.audit3 openssh-6.2p1/Makefile.in
|
||||
--- openssh-6.2p1/Makefile.in.audit3 2013-03-25 17:30:41.337102676 +0100
|
||||
+++ openssh-6.2p1/Makefile.in 2013-03-25 17:33:18.833004685 +0100
|
||||
@@ -73,7 +73,7 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.o
|
||||
monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
|
||||
kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \
|
||||
msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
|
||||
- jpake.o schnorr.o ssh-pkcs11.o krl.o
|
||||
+ jpake.o schnorr.o ssh-pkcs11.o krl.o auditstub.o
|
||||
|
||||
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
|
||||
sshconnect.o sshconnect1.o sshconnect2.o mux.o \
|
||||
diff -up openssh-6.2p1/monitor.c.audit3 openssh-6.2p1/monitor.c
|
||||
--- openssh-6.2p1/monitor.c.audit3 2013-03-25 17:30:41.333102653 +0100
|
||||
+++ openssh-6.2p1/monitor.c 2013-03-25 17:30:41.344102717 +0100
|
||||
@@ -97,6 +97,7 @@
|
||||
#include "ssh2.h"
|
||||
#include "jpake.h"
|
||||
#include "roaming.h"
|
||||
+#include "audit.h"
|
||||
|
||||
#ifdef GSSAPI
|
||||
static Gssctxt *gsscontext = NULL;
|
||||
@@ -186,6 +187,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},
|
||||
@@ -274,6 +279,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}
|
||||
};
|
||||
@@ -305,6 +312,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}
|
||||
};
|
||||
@@ -317,6 +326,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}
|
||||
};
|
||||
@@ -2397,3 +2408,47 @@ 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);
|
||||
+
|
||||
+ xfree(cipher);
|
||||
+ xfree(mac);
|
||||
+ xfree(compress);
|
||||
+ buffer_clear(m);
|
||||
+
|
||||
+ mm_request_send(sock, MONITOR_ANS_AUDIT_KEX, m);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#endif /* SSH_AUDIT_EVENTS */
|
||||
diff -up openssh-6.2p1/monitor.h.audit3 openssh-6.2p1/monitor.h
|
||||
--- openssh-6.2p1/monitor.h.audit3 2013-03-25 17:30:41.345102722 +0100
|
||||
+++ openssh-6.2p1/monitor.h 2013-03-25 17:31:57.314538661 +0100
|
||||
@@ -70,7 +70,9 @@ enum monitor_reqtype {
|
||||
MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111,
|
||||
MONITOR_REQ_AUDIT_EVENT = 112,
|
||||
MONITOR_REQ_AUDIT_COMMAND = 114, MONITOR_ANS_AUDIT_COMMAND = 115,
|
||||
- MONITOR_REQ_AUDIT_END_COMMAND = 116
|
||||
+ MONITOR_REQ_AUDIT_END_COMMAND = 116,
|
||||
+ MONITOR_REQ_AUDIT_UNSUPPORTED = 118, MONITOR_ANS_AUDIT_UNSUPPORTED = 119,
|
||||
+ MONITOR_REQ_AUDIT_KEX = 120, MONITOR_ANS_AUDIT_KEX = 121
|
||||
|
||||
};
|
||||
|
||||
diff -up openssh-6.2p1/monitor_wrap.c.audit3 openssh-6.2p1/monitor_wrap.c
|
||||
--- openssh-6.2p1/monitor_wrap.c.audit3 2013-03-25 17:30:41.334102659 +0100
|
||||
+++ openssh-6.2p1/monitor_wrap.c 2013-03-25 17:30:41.346102728 +0100
|
||||
@@ -1486,3 +1486,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-6.2p1/monitor_wrap.h.audit3 openssh-6.2p1/monitor_wrap.h
|
||||
--- openssh-6.2p1/monitor_wrap.h.audit3 2013-03-25 17:30:41.334102659 +0100
|
||||
+++ openssh-6.2p1/monitor_wrap.h 2013-03-25 17:30:41.346102728 +0100
|
||||
@@ -77,6 +77,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-6.2p1/sshd.c.audit3 openssh-6.2p1/sshd.c
|
||||
--- openssh-6.2p1/sshd.c.audit3 2013-03-25 17:30:41.326102613 +0100
|
||||
+++ openssh-6.2p1/sshd.c 2013-03-25 17:30:41.348102740 +0100
|
||||
@@ -118,6 +118,7 @@
|
||||
#endif
|
||||
#include "monitor_wrap.h"
|
||||
#include "roaming.h"
|
||||
+#include "audit.h"
|
||||
#include "ssh-sandbox.h"
|
||||
#include "version.h"
|
||||
|
||||
@@ -2241,6 +2242,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. */
|
@ -1,666 +0,0 @@
|
||||
diff -up openssh-6.2p1/audit-bsm.c.audit4 openssh-6.2p1/audit-bsm.c
|
||||
--- openssh-6.2p1/audit-bsm.c.audit4 2013-03-25 17:34:16.034337746 +0100
|
||||
+++ openssh-6.2p1/audit-bsm.c 2013-03-25 17:34:16.042337793 +0100
|
||||
@@ -485,4 +485,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-6.2p1/audit.c.audit4 openssh-6.2p1/audit.c
|
||||
--- openssh-6.2p1/audit.c.audit4 2013-03-25 17:34:16.035337752 +0100
|
||||
+++ openssh-6.2p1/audit.c 2013-03-25 17:34:16.042337793 +0100
|
||||
@@ -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-6.2p1/audit.h.audit4 openssh-6.2p1/audit.h
|
||||
--- openssh-6.2p1/audit.h.audit4 2013-03-25 17:34:16.035337752 +0100
|
||||
+++ openssh-6.2p1/audit.h 2013-03-25 17:34:16.043337799 +0100
|
||||
@@ -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-6.2p1/audit-linux.c.audit4 openssh-6.2p1/audit-linux.c
|
||||
--- openssh-6.2p1/audit-linux.c.audit4 2013-03-25 17:34:16.035337752 +0100
|
||||
+++ openssh-6.2p1/audit-linux.c 2013-03-25 17:34:16.043337799 +0100
|
||||
@@ -294,6 +294,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)
|
||||
@@ -301,7 +303,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);
|
||||
char *s;
|
||||
|
||||
@@ -327,4 +328,32 @@ 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;
|
||||
+ char *s;
|
||||
+
|
||||
+ 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(),
|
||||
+ (s = get_local_ipaddr(packet_get_connection_in())),
|
||||
+ get_local_port());
|
||||
+ xfree(s);
|
||||
+ 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-6.2p1/auditstub.c.audit4 openssh-6.2p1/auditstub.c
|
||||
--- openssh-6.2p1/auditstub.c.audit4 2013-03-25 17:34:16.035337752 +0100
|
||||
+++ openssh-6.2p1/auditstub.c 2013-03-25 17:34:16.043337799 +0100
|
||||
@@ -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-6.2p1/kex.c.audit4 openssh-6.2p1/kex.c
|
||||
--- openssh-6.2p1/kex.c.audit4 2013-03-25 17:34:16.036337758 +0100
|
||||
+++ openssh-6.2p1/kex.c 2013-03-25 17:34:16.044337804 +0100
|
||||
@@ -640,3 +640,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-6.2p1/kex.h.audit4 openssh-6.2p1/kex.h
|
||||
--- openssh-6.2p1/kex.h.audit4 2013-01-09 06:12:19.000000000 +0100
|
||||
+++ openssh-6.2p1/kex.h 2013-03-25 17:34:16.044337804 +0100
|
||||
@@ -158,6 +158,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-6.2p1/mac.c.audit4 openssh-6.2p1/mac.c
|
||||
--- openssh-6.2p1/mac.c.audit4 2012-12-12 01:00:37.000000000 +0100
|
||||
+++ openssh-6.2p1/mac.c 2013-03-25 17:34:16.044337804 +0100
|
||||
@@ -199,6 +199,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-6.2p1/mac.h.audit4 openssh-6.2p1/mac.h
|
||||
--- openssh-6.2p1/mac.h.audit4 2007-06-11 06:01:42.000000000 +0200
|
||||
+++ openssh-6.2p1/mac.h 2013-03-25 17:34:16.045337810 +0100
|
||||
@@ -28,3 +28,4 @@ int mac_setup(Mac *, char *);
|
||||
int mac_init(Mac *);
|
||||
u_char *mac_compute(Mac *, u_int32_t, u_char *, int);
|
||||
void mac_clear(Mac *);
|
||||
+void mac_destroy(Mac *);
|
||||
diff -up openssh-6.2p1/monitor.c.audit4 openssh-6.2p1/monitor.c
|
||||
--- openssh-6.2p1/monitor.c.audit4 2013-03-25 17:34:16.037337763 +0100
|
||||
+++ openssh-6.2p1/monitor.c 2013-03-25 17:34:16.046337816 +0100
|
||||
@@ -189,6 +189,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},
|
||||
@@ -281,6 +283,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}
|
||||
};
|
||||
@@ -314,6 +317,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}
|
||||
};
|
||||
@@ -328,6 +332,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}
|
||||
};
|
||||
@@ -1957,11 +1962,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 */
|
||||
@@ -2007,6 +2014,21 @@ 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
|
||||
+
|
||||
+ /* Drain any buffered messages from the child */
|
||||
+ while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0)
|
||||
+ ;
|
||||
+
|
||||
}
|
||||
|
||||
|
||||
@@ -2451,4 +2473,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-6.2p1/monitor.h.audit4 openssh-6.2p1/monitor.h
|
||||
--- openssh-6.2p1/monitor.h.audit4 2013-03-25 17:34:16.046337816 +0100
|
||||
+++ openssh-6.2p1/monitor.h 2013-03-25 17:35:01.408602217 +0100
|
||||
@@ -72,7 +72,8 @@ enum monitor_reqtype {
|
||||
MONITOR_REQ_AUDIT_COMMAND = 114, MONITOR_ANS_AUDIT_COMMAND = 115,
|
||||
MONITOR_REQ_AUDIT_END_COMMAND = 116,
|
||||
MONITOR_REQ_AUDIT_UNSUPPORTED = 118, MONITOR_ANS_AUDIT_UNSUPPORTED = 119,
|
||||
- MONITOR_REQ_AUDIT_KEX = 120, MONITOR_ANS_AUDIT_KEX = 121
|
||||
+ MONITOR_REQ_AUDIT_KEX = 120, MONITOR_ANS_AUDIT_KEX = 121,
|
||||
+ MONITOR_REQ_AUDIT_SESSION_KEY_FREE = 122, MONITOR_ANS_AUDIT_SESSION_KEY_FREE = 123
|
||||
|
||||
};
|
||||
|
||||
diff -up openssh-6.2p1/monitor_wrap.c.audit4 openssh-6.2p1/monitor_wrap.c
|
||||
--- openssh-6.2p1/monitor_wrap.c.audit4 2013-03-25 17:34:16.038337769 +0100
|
||||
+++ openssh-6.2p1/monitor_wrap.c 2013-03-25 17:34:16.047337822 +0100
|
||||
@@ -654,12 +654,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);
|
||||
@@ -1523,4 +1525,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-6.2p1/monitor_wrap.h.audit4 openssh-6.2p1/monitor_wrap.h
|
||||
--- openssh-6.2p1/monitor_wrap.h.audit4 2013-03-25 17:34:16.039337775 +0100
|
||||
+++ openssh-6.2p1/monitor_wrap.h 2013-03-25 17:34:16.047337822 +0100
|
||||
@@ -79,6 +79,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-6.2p1/packet.c.audit4 openssh-6.2p1/packet.c
|
||||
--- openssh-6.2p1/packet.c.audit4 2013-03-25 17:34:16.014337629 +0100
|
||||
+++ openssh-6.2p1/packet.c 2013-03-25 17:42:26.519176337 +0100
|
||||
@@ -60,6 +60,7 @@
|
||||
#include <signal.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
+#include "audit.h"
|
||||
#include "buffer.h"
|
||||
#include "packet.h"
|
||||
#include "crc32.h"
|
||||
@@ -470,6 +471,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
|
||||
@@ -478,13 +486,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);
|
||||
@@ -493,8 +494,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. */
|
||||
@@ -729,6 +740,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)
|
||||
{
|
||||
@@ -754,21 +782,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);
|
||||
- memset(enc->iv, 0, enc->iv_len);
|
||||
- memset(enc->key, 0, enc->key_len);
|
||||
- memset(mac->key, 0, mac->key_len);
|
||||
- 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)
|
||||
@@ -1971,6 +1987,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.
|
||||
@@ -1978,18 +2035,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();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2006,9 +2057,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);
|
||||
@@ -2016,4 +2065,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-6.2p1/packet.h.audit4 openssh-6.2p1/packet.h
|
||||
--- openssh-6.2p1/packet.h.audit4 2012-02-10 22:19:21.000000000 +0100
|
||||
+++ openssh-6.2p1/packet.h 2013-03-25 17:34:16.049337834 +0100
|
||||
@@ -123,4 +123,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-6.2p1/session.c.audit4 openssh-6.2p1/session.c
|
||||
--- openssh-6.2p1/session.c.audit4 2013-03-25 17:34:16.023337682 +0100
|
||||
+++ openssh-6.2p1/session.c 2013-03-25 17:34:16.050337839 +0100
|
||||
@@ -1642,6 +1642,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-6.2p1/sshd.c.audit4 openssh-6.2p1/sshd.c
|
||||
--- openssh-6.2p1/sshd.c.audit4 2013-03-25 17:34:16.039337775 +0100
|
||||
+++ openssh-6.2p1/sshd.c 2013-03-25 17:34:16.050337839 +0100
|
||||
@@ -701,6 +701,8 @@ privsep_preauth(Authctxt *authctxt)
|
||||
}
|
||||
}
|
||||
|
||||
+extern Newkeys *current_keys[];
|
||||
+
|
||||
static void
|
||||
privsep_postauth(Authctxt *authctxt)
|
||||
{
|
||||
@@ -725,6 +727,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 */
|
||||
@@ -2033,6 +2039,7 @@ main(int ac, char **av)
|
||||
*/
|
||||
if (use_privsep) {
|
||||
mm_send_keystate(pmonitor);
|
||||
+ packet_destroy_all(1, 1);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -2085,6 +2092,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",
|
||||
@@ -2402,6 +2411,16 @@ do_ssh2_kex(void)
|
||||
void
|
||||
cleanup_exit(int i)
|
||||
{
|
||||
+ static int in_cleanup = 0;
|
||||
+ 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);
|
||||
if (use_privsep && privsep_is_preauth && pmonitor->m_pid > 1) {
|
||||
@@ -2412,6 +2431,8 @@ cleanup_exit(int i)
|
||||
pmonitor->m_pid, strerror(errno));
|
||||
}
|
||||
}
|
||||
+ is_privsep_child = use_privsep && pmonitor != NULL && !mm_is_monitor();
|
||||
+ 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) &&
|
@ -1,488 +0,0 @@
|
||||
diff -up openssh-6.2p1/audit-bsm.c.audit5 openssh-6.2p1/audit-bsm.c
|
||||
--- openssh-6.2p1/audit-bsm.c.audit5 2013-03-25 17:43:27.495526587 +0100
|
||||
+++ openssh-6.2p1/audit-bsm.c 2013-03-25 17:43:27.502526627 +0100
|
||||
@@ -491,4 +491,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-6.2p1/audit.c.audit5 openssh-6.2p1/audit.c
|
||||
--- openssh-6.2p1/audit.c.audit5 2013-03-25 17:43:27.495526587 +0100
|
||||
+++ openssh-6.2p1/audit.c 2013-03-25 17:43:27.502526627 +0100
|
||||
@@ -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-6.2p1/audit.h.audit5 openssh-6.2p1/audit.h
|
||||
--- openssh-6.2p1/audit.h.audit5 2013-03-25 17:43:27.496526593 +0100
|
||||
+++ openssh-6.2p1/audit.h 2013-03-25 17:43:27.502526627 +0100
|
||||
@@ -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-6.2p1/audit-linux.c.audit5 openssh-6.2p1/audit-linux.c
|
||||
--- openssh-6.2p1/audit-linux.c.audit5 2013-03-25 17:43:27.496526593 +0100
|
||||
+++ openssh-6.2p1/audit-linux.c 2013-03-25 17:43:27.503526633 +0100
|
||||
@@ -356,4 +356,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-6.2p1/key.c.audit5 openssh-6.2p1/key.c
|
||||
--- openssh-6.2p1/key.c.audit5 2013-03-25 17:43:27.465526415 +0100
|
||||
+++ openssh-6.2p1/key.c 2013-03-25 17:43:27.503526633 +0100
|
||||
@@ -1809,6 +1809,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-6.2p1/key.h.audit5 openssh-6.2p1/key.h
|
||||
--- openssh-6.2p1/key.h.audit5 2013-03-25 17:43:27.465526415 +0100
|
||||
+++ openssh-6.2p1/key.h 2013-03-25 17:43:27.503526633 +0100
|
||||
@@ -110,6 +110,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-6.2p1/monitor.c.audit5 openssh-6.2p1/monitor.c
|
||||
--- openssh-6.2p1/monitor.c.audit5 2013-03-25 17:43:27.497526599 +0100
|
||||
+++ openssh-6.2p1/monitor.c 2013-03-25 17:43:27.504526639 +0100
|
||||
@@ -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 {
|
||||
@@ -190,6 +192,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},
|
||||
@@ -284,6 +288,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}
|
||||
};
|
||||
@@ -318,6 +323,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}
|
||||
};
|
||||
@@ -333,6 +339,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}
|
||||
};
|
||||
@@ -1752,6 +1759,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);
|
||||
@@ -2491,4 +2500,25 @@ 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);
|
||||
+
|
||||
+ xfree(fp);
|
||||
+ buffer_clear(m);
|
||||
+
|
||||
+ mm_request_send(sock, MONITOR_ANS_AUDIT_SERVER_KEY_FREE, m);
|
||||
+ return 0;
|
||||
+}
|
||||
#endif /* SSH_AUDIT_EVENTS */
|
||||
diff -up openssh-6.2p1/monitor.h.audit5 openssh-6.2p1/monitor.h
|
||||
--- openssh-6.2p1/monitor.h.audit5 2013-03-25 17:43:27.504526639 +0100
|
||||
+++ openssh-6.2p1/monitor.h 2013-03-25 17:44:08.717763090 +0100
|
||||
@@ -73,7 +73,8 @@ enum monitor_reqtype {
|
||||
MONITOR_REQ_AUDIT_END_COMMAND = 116,
|
||||
MONITOR_REQ_AUDIT_UNSUPPORTED = 118, MONITOR_ANS_AUDIT_UNSUPPORTED = 119,
|
||||
MONITOR_REQ_AUDIT_KEX = 120, MONITOR_ANS_AUDIT_KEX = 121,
|
||||
- MONITOR_REQ_AUDIT_SESSION_KEY_FREE = 122, MONITOR_ANS_AUDIT_SESSION_KEY_FREE = 123
|
||||
+ MONITOR_REQ_AUDIT_SESSION_KEY_FREE = 122, MONITOR_ANS_AUDIT_SESSION_KEY_FREE = 123,
|
||||
+ MONITOR_REQ_AUDIT_SERVER_KEY_FREE = 124, MONITOR_ANS_AUDIT_SERVER_KEY_FREE = 125
|
||||
|
||||
};
|
||||
|
||||
diff -up openssh-6.2p1/monitor_wrap.c.audit5 openssh-6.2p1/monitor_wrap.c
|
||||
--- openssh-6.2p1/monitor_wrap.c.audit5 2013-03-25 17:43:27.498526604 +0100
|
||||
+++ openssh-6.2p1/monitor_wrap.c 2013-03-25 17:43:27.505526645 +0100
|
||||
@@ -1540,4 +1540,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-6.2p1/monitor_wrap.h.audit5 openssh-6.2p1/monitor_wrap.h
|
||||
--- openssh-6.2p1/monitor_wrap.h.audit5 2013-03-25 17:43:27.498526604 +0100
|
||||
+++ openssh-6.2p1/monitor_wrap.h 2013-03-25 17:43:27.505526645 +0100
|
||||
@@ -80,6 +80,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-6.2p1/session.c.audit5 openssh-6.2p1/session.c
|
||||
--- openssh-6.2p1/session.c.audit5 2013-03-25 17:43:27.499526610 +0100
|
||||
+++ openssh-6.2p1/session.c 2013-03-25 17:43:27.506526650 +0100
|
||||
@@ -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. */
|
||||
@@ -1641,7 +1641,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-6.2p1/sshd.c.audit5 openssh-6.2p1/sshd.c
|
||||
--- openssh-6.2p1/sshd.c.audit5 2013-03-25 17:43:27.500526616 +0100
|
||||
+++ openssh-6.2p1/sshd.c 2013-03-25 17:43:27.506526650 +0100
|
||||
@@ -255,7 +255,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);
|
||||
@@ -274,6 +274,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)
|
||||
{
|
||||
@@ -545,22 +554,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;
|
||||
}
|
||||
@@ -574,6 +608,8 @@ void
|
||||
demote_sensitive_data(void)
|
||||
{
|
||||
Key *tmp;
|
||||
+ pid_t pid;
|
||||
+ uid_t uid;
|
||||
int i;
|
||||
|
||||
if (sensitive_data.server_key) {
|
||||
@@ -582,13 +618,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 */
|
||||
}
|
||||
@@ -1160,6 +1210,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);
|
||||
@@ -2082,7 +2133,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,
|
||||
@@ -2093,6 +2144,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);
|
||||
@@ -2321,7 +2373,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);
|
||||
@@ -2432,6 +2484,8 @@ cleanup_exit(int i)
|
||||
}
|
||||
}
|
||||
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' */
|
60
openssh.spec
60
openssh.spec
@ -77,19 +77,14 @@ Version: %{openssh_ver}
|
||||
Release: %{openssh_rel}%{?dist}%{?rescue_rel}
|
||||
URL: http://www.openssh.com/portable.html
|
||||
#URL1: http://pamsshagentauth.sourceforge.net
|
||||
#Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz
|
||||
Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz
|
||||
#Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc
|
||||
# This package differs from the upstream OpenSSH tarball in that
|
||||
# the ACSS cipher is removed by running openssh-nukeacss.sh in
|
||||
# the unpacked source directory.
|
||||
Source0: openssh-%{version}.tar.gz
|
||||
Source2: sshd.pam
|
||||
Source3: sshd.init
|
||||
Source4: http://prdownloads.sourceforge.net/pamsshagentauth/pam_ssh_agent_auth/pam_ssh_agent_auth-%{pam_ssh_agent_ver}.tar.bz2
|
||||
Source5: pam_ssh_agent-rmheaders
|
||||
Source6: ssh-keycat.pam
|
||||
Source7: sshd.sysconfig
|
||||
Source8: sshd-keygen.service
|
||||
Source9: sshd@.service
|
||||
Source10: sshd.socket
|
||||
Source11: sshd.service
|
||||
@ -107,22 +102,9 @@ Patch101: openssh-6.2p1-fingerprint.patch
|
||||
Patch102: openssh-5.8p1-getaddrinfo.patch
|
||||
#https://bugzilla.mindrot.org/show_bug.cgi?id=1889
|
||||
Patch103: openssh-5.8p1-packet.patch
|
||||
#https://bugzilla.mindrot.org/show_bug.cgi?id=983
|
||||
Patch104: openssh-6.1p1-authenticationmethods.patch
|
||||
|
||||
#https://bugzilla.mindrot.org/show_bug.cgi?id=1402
|
||||
Patch200: openssh-6.2p1-audit.patch
|
||||
# Patch200: openssh-5.8p1-audit0.patch
|
||||
# # -"-
|
||||
# Patch201: openssh-6.2p1-audit1.patch
|
||||
# # -"-
|
||||
# Patch202: openssh-5.9p1-audit2.patch
|
||||
# # -"-
|
||||
# Patch203: openssh-6.2p1-audit3.patch
|
||||
# # -"-
|
||||
# Patch204: openssh-6.2p1-audit4.patch
|
||||
# # -"-
|
||||
# Patch205: openssh-6.2p1-audit5.patch
|
||||
|
||||
# --- pam_ssh-agent ---
|
||||
# make it build reusing the openssh sources
|
||||
@ -133,22 +115,14 @@ Patch301: pam_ssh_agent_auth-0.9.2-seteuid.patch
|
||||
Patch302: pam_ssh_agent_auth-0.9.2-visibility.patch
|
||||
#https://bugzilla.mindrot.org/show_bug.cgi?id=1641 (WONTFIX)
|
||||
Patch400: openssh-6.2p1-role-mls.patch
|
||||
#?
|
||||
#Patch402: openssh-5.9p1-sftp-chroot.patch
|
||||
#https://bugzilla.mindrot.org/show_bug.cgi?id=1940
|
||||
#Patch403: openssh-5.9p1-sesandbox.patch
|
||||
#https://bugzilla.redhat.com/show_bug.cgi?id=781634
|
||||
Patch404: openssh-6.1p1-privsep-selinux.patch
|
||||
|
||||
#https://bugzilla.mindrot.org/show_bug.cgi?id=1663
|
||||
Patch500: openssh-6.1p1-akc.patch
|
||||
#?-- unwanted child :(
|
||||
Patch501: openssh-6.2p1-ldap.patch
|
||||
#?
|
||||
Patch502: openssh-6.2p1-keycat.patch
|
||||
|
||||
#https://bugzilla.mindrot.org/show_bug.cgi?id=1668
|
||||
#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
|
||||
@ -188,8 +162,6 @@ Patch707: openssh-6.1p1-redhat.patch
|
||||
Patch708: openssh-6.2p1-entropy.patch
|
||||
#https://bugzilla.mindrot.org/show_bug.cgi?id=1640 (WONTFIX)
|
||||
Patch709: openssh-6.2p1-vendor.patch
|
||||
#?
|
||||
Patch710: openssh-5.9p1-copy-id-restorecon.patch
|
||||
# warn users for unsupported UsePAM=no (#757545)
|
||||
Patch711: openssh-6.1p1-log-usepam-no.patch
|
||||
# make aes-ctr ciphers use EVP engines such as AES-NI from OpenSSL
|
||||
@ -206,12 +178,6 @@ Patch801: openssh-6.2p1-force_krb.patch
|
||||
Patch900: openssh-6.1p1-gssapi-canohost.patch
|
||||
#https://bugzilla.mindrot.org/show_bug.cgi?id=1780
|
||||
Patch901: openssh-6.2p1-kuserok.patch
|
||||
#https://bugzilla.redhat.com/show_bug.cgi?id=841065
|
||||
Patch902: openssh-6.1p1-man-moduli.patch
|
||||
# obsolete RequiredAuthentications options
|
||||
Patch903: openssh-6.1p1-required-authentications.patch
|
||||
# change default value of MaxStartups - CVE-2010-5107 - #908707
|
||||
Patch904: openssh-6.1p1-change-max-startups.patch
|
||||
|
||||
# build regress/modpipe tests with $(CFLAGS), based on
|
||||
# http://lists.mindrot.org/pipermail/openssh-unix-dev/2013-March/031167.html
|
||||
@ -221,10 +187,6 @@ Patch906: openssh-6.2p1-track-IdentifyFile.patch
|
||||
# add latest config.{sub,guess} to support aarch64 (#926284)
|
||||
Patch907: openssh-6.2p1-aarch64.patch
|
||||
|
||||
#---
|
||||
#https://bugzilla.mindrot.org/show_bug.cgi?id=1604
|
||||
# sctp
|
||||
#https://bugzilla.mindrot.org/show_bug.cgi?id=1873 => https://bugzilla.redhat.com/show_bug.cgi?id=668993
|
||||
|
||||
License: BSD
|
||||
Group: Applications/Internet
|
||||
@ -287,10 +249,6 @@ Requires: fipscheck-lib%{_isa} >= 1.3.0
|
||||
Requires(post): systemd-units
|
||||
Requires(preun): systemd-units
|
||||
Requires(postun): systemd-units
|
||||
# This is actually needed for the %triggerun script but Requires(triggerun)
|
||||
# is not valid. We can use %post because this particular %triggerun script
|
||||
# should fire just after this package is installed.
|
||||
Requires(post): systemd-sysv
|
||||
|
||||
# Not yet ready
|
||||
# %package server-ondemand
|
||||
@ -401,15 +359,8 @@ The module is most useful for su and sudo service stacks.
|
||||
%patch101 -p1 -b .fingerprint
|
||||
%patch102 -p1 -b .getaddrinfo
|
||||
%patch103 -p1 -b .packet
|
||||
# %patch104 -p1 -b .authenticationmethods
|
||||
|
||||
%patch200 -p1 -b .audit
|
||||
# %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}
|
||||
@ -423,18 +374,14 @@ popd
|
||||
|
||||
%if %{WITH_SELINUX}
|
||||
%patch400 -p1 -b .role-mls
|
||||
# %patch402 -p1 -b .sftp-chroot
|
||||
# %patch403 -p1 -b .sesandbox
|
||||
%patch404 -p1 -b .privsep-selinux
|
||||
%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
|
||||
@ -455,7 +402,6 @@ popd
|
||||
%patch707 -p1 -b .redhat
|
||||
%patch708 -p1 -b .entropy
|
||||
%patch709 -p1 -b .vendor
|
||||
# %patch710 -p1 -b .restorecon
|
||||
%patch711 -p1 -b .log-usepam-no
|
||||
%patch712 -p1 -b .evp-ctr
|
||||
%patch713 -p1 -b .ctr-cavs
|
||||
@ -465,9 +411,6 @@ popd
|
||||
|
||||
%patch900 -p1 -b .canohost
|
||||
%patch901 -p1 -b .kuserok
|
||||
# %patch902 -p1 -b .man-moduli
|
||||
# %patch903 -p1 -b .required-authentication
|
||||
# %patch904 -p1 -b .max-startups
|
||||
%patch905 -p1 -b .modpipe-cflags
|
||||
%patch906 -p1 -b .identityfile
|
||||
%patch907 -p1 -b .aarch64
|
||||
@ -625,7 +568,6 @@ install -m755 %{SOURCE3} $RPM_BUILD_ROOT/etc/rc.d/init.d/sshd
|
||||
install -m644 %{SOURCE7} $RPM_BUILD_ROOT/etc/sysconfig/sshd
|
||||
install -m755 %{SOURCE13} $RPM_BUILD_ROOT/%{_sbindir}/sshd-keygen
|
||||
install -d -m755 $RPM_BUILD_ROOT/%{_unitdir}
|
||||
# install -m644 %{SOURCE8} $RPM_BUILD_ROOT/%{_unitdir}/sshd-keygen.service
|
||||
# install -m644 %{SOURCE9} $RPM_BUILD_ROOT/%{_unitdir}/sshd@.service
|
||||
# install -m644 %{SOURCE10} $RPM_BUILD_ROOT/%{_unitdir}/sshd.socket
|
||||
install -m644 %{SOURCE11} $RPM_BUILD_ROOT/%{_unitdir}/sshd.service
|
||||
|
@ -1,11 +0,0 @@
|
||||
[Unit]
|
||||
Description=SSH server keys generation.
|
||||
After=syslog.target
|
||||
Before=sshd.service
|
||||
BindTo=sshd.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
EnvironmentFile=/etc/sysconfig/sshd
|
||||
ExecStart=/usr/sbin/sshd-keygen
|
||||
RemainAfterExit=yes
|
Loading…
Reference in New Issue
Block a user