summaryrefslogtreecommitdiff
path: root/crypto
diff options
context:
space:
mode:
authorGlen Barber <gjb@FreeBSD.org>2018-10-08 18:06:40 +0000
committerGlen Barber <gjb@FreeBSD.org>2018-10-08 18:06:40 +0000
commitfc3f42d80f90f3c58aa11cf1f35092a9703bd77b (patch)
treec609537bc5aca59f18c13d513aa2972f22abad4a /crypto
parent90682fb3ab3b20e171d3908a4e9bebfbba4f8f99 (diff)
parentf3b515aea565140c93e77011516e9e3cbe7dc0d2 (diff)
downloadsrc-test2-fc3f42d80f90f3c58aa11cf1f35092a9703bd77b.tar.gz
src-test2-fc3f42d80f90f3c58aa11cf1f35092a9703bd77b.zip
MFH r339206-r339212, r339215-r339239
Sponsored by: The FreeBSD Foundation
Notes
Notes: svn path=/projects/openssl111/; revision=339240
Diffstat (limited to 'crypto')
-rw-r--r--crypto/openssh/auth2.c4
-rw-r--r--crypto/openssh/monitor.c55
-rw-r--r--crypto/openssh/monitor.h3
-rw-r--r--crypto/openssh/monitor_wrap.c73
-rw-r--r--crypto/openssh/monitor_wrap.h4
-rw-r--r--crypto/openssh/sandbox-capsicum.c3
-rw-r--r--crypto/openssh/sshbuf-getput-basic.c93
-rw-r--r--crypto/openssh/sshbuf.h16
-rw-r--r--crypto/openssh/sshd.c5
9 files changed, 222 insertions, 34 deletions
diff --git a/crypto/openssh/auth2.c b/crypto/openssh/auth2.c
index fe9b1f950198..588a8346c43e 100644
--- a/crypto/openssh/auth2.c
+++ b/crypto/openssh/auth2.c
@@ -316,7 +316,7 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
#ifdef HAVE_LOGIN_CAP
if (authctxt->pw != NULL &&
- (lc = login_getpwclass(authctxt->pw)) != NULL) {
+ (lc = PRIVSEP(login_getpwclass(authctxt->pw))) != NULL) {
logit("user %s login class %s", authctxt->pw->pw_name,
authctxt->pw->pw_class);
from_host = auth_get_canonical_hostname(ssh, options.use_dns);
@@ -331,7 +331,7 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
authctxt->pw->pw_name, from_host);
packet_disconnect("Logins not available right now.");
}
- login_close(lc);
+ PRIVSEP(login_close(lc));
}
#endif /* HAVE_LOGIN_CAP */
diff --git a/crypto/openssh/monitor.c b/crypto/openssh/monitor.c
index 531b2993ab6b..3c0c23393945 100644
--- a/crypto/openssh/monitor.c
+++ b/crypto/openssh/monitor.c
@@ -114,6 +114,7 @@ static struct sshbuf *child_state;
int mm_answer_moduli(int, struct sshbuf *);
int mm_answer_sign(int, struct sshbuf *);
+int mm_answer_login_getpwclass(int, struct sshbuf *);
int mm_answer_pwnamallow(int, struct sshbuf *);
int mm_answer_auth2_read_banner(int, struct sshbuf *);
int mm_answer_authserv(int, struct sshbuf *);
@@ -189,6 +190,7 @@ struct mon_table mon_dispatch_proto20[] = {
{MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
#endif
{MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
+ {MONITOR_REQ_GETPWCLASS, MON_AUTH, mm_answer_login_getpwclass},
{MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
{MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
{MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
@@ -707,6 +709,46 @@ mm_answer_sign(int sock, struct sshbuf *m)
return (0);
}
+int
+mm_answer_login_getpwclass(int sock, struct sshbuf *m)
+{
+ login_cap_t *lc;
+ struct passwd *pw;
+ int r;
+ u_int len;
+
+ debug3("%s", __func__);
+
+ pw = sshbuf_get_passwd(m);
+ if (pw == NULL)
+ fatal("%s: receive get struct passwd failed", __func__);
+
+ lc = login_getpwclass(pw);
+
+ sshbuf_reset(m);
+
+ if (lc == NULL) {
+ if (r = sshbuf_put_u8(m, 0) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ goto out;
+ }
+
+ if ((r = sshbuf_put_u8(m, 1)) != 0 ||
+ (r = sshbuf_put_cstring(m, lc->lc_class)) != 0 ||
+ (r = sshbuf_put_cstring(m, lc->lc_cap)) != 0 ||
+ (r = sshbuf_put_cstring(m, lc->lc_style)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+
+ login_close(lc);
+ out:
+ debug3("%s: sending MONITOR_ANS_GETPWCLASS", __func__);
+ mm_request_send(sock, MONITOR_ANS_GETPWCLASS, m);
+
+ sshbuf_free_passwd(pw);
+
+ return (0);
+}
+
/* Retrieves the password entry and also checks if the user is permitted */
int
@@ -745,19 +787,8 @@ mm_answer_pwnamallow(int sock, struct sshbuf *m)
authctxt->pw = pwent;
authctxt->valid = 1;
- /* XXX don't sent pwent to unpriv; send fake class/dir/shell too */
if ((r = sshbuf_put_u8(m, 1)) != 0 ||
- (r = sshbuf_put_string(m, pwent, sizeof(*pwent))) != 0 ||
- (r = sshbuf_put_cstring(m, pwent->pw_name)) != 0 ||
- (r = sshbuf_put_cstring(m, "*")) != 0 ||
-#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
- (r = sshbuf_put_cstring(m, pwent->pw_gecos)) != 0 ||
-#endif
-#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
- (r = sshbuf_put_cstring(m, pwent->pw_class)) != 0 ||
-#endif
- (r = sshbuf_put_cstring(m, pwent->pw_dir)) != 0 ||
- (r = sshbuf_put_cstring(m, pwent->pw_shell)) != 0)
+ (r = sshbuf_put_passwd(m, pwent)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r));
out:
diff --git a/crypto/openssh/monitor.h b/crypto/openssh/monitor.h
index 16047299f882..abf2ca4018b4 100644
--- a/crypto/openssh/monitor.h
+++ b/crypto/openssh/monitor.h
@@ -53,7 +53,8 @@ enum monitor_reqtype {
MONITOR_REQ_GSSSTEP = 44, MONITOR_ANS_GSSSTEP = 45,
MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47,
MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49,
- MONITOR_REQ_TERM = 50,
+ MONITOR_REQ_GETPWCLASS = 50, MONITOR_ANS_GETPWCLASS = 51,
+ MONITOR_REQ_TERM = 52,
MONITOR_REQ_PAM_START = 100,
MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103,
diff --git a/crypto/openssh/monitor_wrap.c b/crypto/openssh/monitor_wrap.c
index 732fb3476bf0..7cd20089d9ca 100644
--- a/crypto/openssh/monitor_wrap.c
+++ b/crypto/openssh/monitor_wrap.c
@@ -247,6 +247,57 @@ mm_sshkey_sign(struct sshkey *key, u_char **sigp, size_t *lenp,
return (0);
}
+login_cap_t *
+mm_login_getpwclass(const struct passwd *pwent)
+{
+ int r;
+ struct sshbuf *m;
+ char rc;
+ login_cap_t *lc;
+
+ debug3("%s entering", __func__);
+
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_passwd(m, pwent)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GETPWCLASS, m);
+
+ debug3("%s: waiting for MONITOR_ANS_GETPWCLASS", __func__);
+ mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GETPWCLASS, m);
+
+ if ((r = sshbuf_get_u8(m, &rc)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+
+ if (rc == 0) {
+ lc = NULL;
+ goto out;
+ }
+
+ lc = xmalloc(sizeof(*lc));
+ if ((r = sshbuf_get_cstring(m, &lc->lc_class, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(m, &lc->lc_cap, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(m, &lc->lc_style, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+
+ out:
+ sshbuf_free(m);
+
+ return (lc);
+}
+
+void
+mm_login_close(login_cap_t *lc)
+{
+ if (lc == NULL)
+ return;
+ free(lc->lc_style);
+ free(lc->lc_class);
+ free(lc->lc_cap);
+ free(lc);
+}
+
struct passwd *
mm_getpwnamallow(const char *username)
{
@@ -279,25 +330,9 @@ mm_getpwnamallow(const char *username)
goto out;
}
- /* XXX don't like passing struct passwd like this */
- pw = xcalloc(sizeof(*pw), 1);
- if ((r = sshbuf_get_string_direct(m, &p, &len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (len != sizeof(*pw))
- fatal("%s: struct passwd size mismatch", __func__);
- memcpy(pw, p, sizeof(*pw));
-
- if ((r = sshbuf_get_cstring(m, &pw->pw_name, NULL)) != 0 ||
- (r = sshbuf_get_cstring(m, &pw->pw_passwd, NULL)) != 0 ||
-#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
- (r = sshbuf_get_cstring(m, &pw->pw_gecos, NULL)) != 0 ||
-#endif
-#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
- (r = sshbuf_get_cstring(m, &pw->pw_class, NULL)) != 0 ||
-#endif
- (r = sshbuf_get_cstring(m, &pw->pw_dir, NULL)) != 0 ||
- (r = sshbuf_get_cstring(m, &pw->pw_shell, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ pw = sshbuf_get_passwd(m);
+ if (pw == NULL)
+ fatal("%s: receive get struct passwd failed", __func__);
out:
/* copy options block as a Match directive may have changed some */
diff --git a/crypto/openssh/monitor_wrap.h b/crypto/openssh/monitor_wrap.h
index 644da081db8d..248dac5c3bb8 100644
--- a/crypto/openssh/monitor_wrap.h
+++ b/crypto/openssh/monitor_wrap.h
@@ -28,6 +28,8 @@
#ifndef _MM_WRAP_H_
#define _MM_WRAP_H_
+#include <login_cap.h>
+
extern int use_privsep;
#define PRIVSEP(x) (use_privsep ? mm_##x : x)
@@ -45,6 +47,8 @@ int mm_sshkey_sign(struct sshkey *, u_char **, size_t *, const u_char *, size_t,
const char *, u_int compat);
void mm_inform_authserv(char *, char *);
struct passwd *mm_getpwnamallow(const char *);
+login_cap_t *mm_login_getpwclass(const struct passwd *pwd);
+void mm_login_close(login_cap_t *lc);
char *mm_auth2_read_banner(void);
int mm_auth_password(struct ssh *, char *);
int mm_key_allowed(enum mm_keytype, const char *, const char *, struct sshkey *,
diff --git a/crypto/openssh/sandbox-capsicum.c b/crypto/openssh/sandbox-capsicum.c
index 5f41d526292b..f728abd18250 100644
--- a/crypto/openssh/sandbox-capsicum.c
+++ b/crypto/openssh/sandbox-capsicum.c
@@ -31,6 +31,7 @@ __RCSID("$FreeBSD$");
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <capsicum_helpers.h>
#include "log.h"
#include "monitor.h"
@@ -71,6 +72,8 @@ ssh_sandbox_child(struct ssh_sandbox *box)
struct rlimit rl_zero;
cap_rights_t rights;
+ caph_cache_tzdata();
+
rl_zero.rlim_cur = rl_zero.rlim_max = 0;
if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1)
diff --git a/crypto/openssh/sshbuf-getput-basic.c b/crypto/openssh/sshbuf-getput-basic.c
index 50648258f48d..ef56931d522e 100644
--- a/crypto/openssh/sshbuf-getput-basic.c
+++ b/crypto/openssh/sshbuf-getput-basic.c
@@ -25,6 +25,7 @@
#include <stdio.h>
#include <string.h>
+#include "xmalloc.h"
#include "ssherr.h"
#include "sshbuf.h"
@@ -462,3 +463,95 @@ sshbuf_get_bignum2_bytes_direct(struct sshbuf *buf,
}
return 0;
}
+
+/*
+ * store struct pwd
+ */
+int
+sshbuf_put_passwd(struct sshbuf *buf, const struct passwd *pwent)
+{
+ int r;
+
+ /*
+ * We never send pointer values of struct passwd.
+ * It is safe from wild pointer even if a new pointer member is added.
+ */
+
+ if ((r = sshbuf_put_u64(buf, sizeof(*pwent)) != 0) ||
+ (r = sshbuf_put_cstring(buf, pwent->pw_name)) != 0 ||
+ (r = sshbuf_put_cstring(buf, "*")) != 0 ||
+ (r = sshbuf_put_u32(buf, pwent->pw_uid)) != 0 ||
+ (r = sshbuf_put_u32(buf, pwent->pw_gid)) != 0 ||
+ (r = sshbuf_put_u64(buf, pwent->pw_change)) != 0 ||
+#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
+ (r = sshbuf_put_cstring(buf, pwent->pw_gecos)) != 0 ||
+#endif
+#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
+ (r = sshbuf_put_cstring(buf, pwent->pw_class)) != 0 ||
+#endif
+ (r = sshbuf_put_cstring(buf, pwent->pw_dir)) != 0 ||
+ (r = sshbuf_put_cstring(buf, pwent->pw_shell)) != 0 ||
+ (r = sshbuf_put_u64(buf, pwent->pw_expire)) != 0 ||
+ (r = sshbuf_put_u32(buf, pwent->pw_fields)) != 0) {
+ return r;
+ }
+ return 0;
+}
+
+/*
+ * extract struct pwd
+ */
+struct passwd *
+sshbuf_get_passwd(struct sshbuf *buf)
+{
+ struct passwd *pw;
+ int r;
+ size_t len;
+
+ /* check if size of struct passwd is as same as sender's size */
+ r = sshbuf_get_u64(buf, &len);
+ if (r != 0 || len != sizeof(*pw))
+ return NULL;
+
+ pw = xcalloc(1, sizeof(*pw));
+ if (sshbuf_get_cstring(buf, &pw->pw_name, NULL) != 0 ||
+ sshbuf_get_cstring(buf, &pw->pw_passwd, NULL) != 0 ||
+ sshbuf_get_u32(buf, &pw->pw_uid) != 0 ||
+ sshbuf_get_u32(buf, &pw->pw_gid) != 0 ||
+ sshbuf_get_u64(buf, &pw->pw_change) != 0 ||
+#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
+ sshbuf_get_cstring(buf, &pw->pw_gecos, NULL) != 0 ||
+#endif
+#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
+ sshbuf_get_cstring(buf, &pw->pw_class, NULL) != 0 ||
+#endif
+ sshbuf_get_cstring(buf, &pw->pw_dir, NULL) != 0 ||
+ sshbuf_get_cstring(buf, &pw->pw_shell, NULL) != 0 ||
+ sshbuf_get_u64(buf, &pw->pw_expire) != 0 ||
+ sshbuf_get_u32(buf, &pw->pw_fields) != 0) {
+ sshbuf_free_passwd(pw);
+ return NULL;
+ }
+ return pw;
+}
+
+/*
+ * free struct passwd obtained from sshbuf_get_passwd.
+ */
+void
+sshbuf_free_passwd(struct passwd *pwent)
+{
+ if (pwent == NULL)
+ return;
+ free(pwent->pw_shell);
+ free(pwent->pw_dir);
+#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
+ free(pwent->pw_class);
+#endif
+#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
+ free(pwent->pw_gecos);
+#endif
+ free(pwent->pw_passwd);
+ free(pwent->pw_name);
+ free(pwent);
+}
diff --git a/crypto/openssh/sshbuf.h b/crypto/openssh/sshbuf.h
index a43598cac4de..1f6f5ead213f 100644
--- a/crypto/openssh/sshbuf.h
+++ b/crypto/openssh/sshbuf.h
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <stdarg.h>
#include <stdio.h>
+#include <pwd.h>
#ifdef WITH_OPENSSL
# include <openssl/bn.h>
# ifdef OPENSSL_HAS_ECC
@@ -246,6 +247,21 @@ int sshbuf_b64tod(struct sshbuf *buf, const char *b64);
*/
char *sshbuf_dup_string(struct sshbuf *buf);
+/*
+ * store struct pwd
+ */
+int sshbuf_put_passwd(struct sshbuf *buf, const struct passwd *pwent);
+
+/*
+ * extract struct pwd
+ */
+struct passwd *sshbuf_get_passwd(struct sshbuf *buf);
+
+/*
+ * free struct passwd obtained from sshbuf_get_passwd.
+ */
+void sshbuf_free_passwd(struct passwd *pwent);
+
/* Macros for decoding/encoding integers */
#define PEEK_U64(p) \
(((u_int64_t)(((const u_char *)(p))[0]) << 56) | \
diff --git a/crypto/openssh/sshd.c b/crypto/openssh/sshd.c
index 8c23b1c92e90..04f875f092a2 100644
--- a/crypto/openssh/sshd.c
+++ b/crypto/openssh/sshd.c
@@ -2143,6 +2143,11 @@ main(int ac, char **av)
*/
remote_ip = ssh_remote_ipaddr(ssh);
+#ifdef HAVE_LOGIN_CAP
+ /* Also caches remote hostname for sandboxed child. */
+ auth_get_canonical_hostname(ssh, options.use_dns);
+#endif
+
#ifdef SSH_AUDIT_EVENTS
audit_connection_from(remote_ip, remote_port);
#endif