summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd.h4
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_krb5ssp.c73
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_logon.c121
-rwxr-xr-xusr/src/tools/quick/make-smbsrv4
4 files changed, 142 insertions, 60 deletions
diff --git a/usr/src/cmd/smbsrv/smbd/smbd.h b/usr/src/cmd/smbsrv/smbd/smbd.h
index c389813f9d..50fad9b41b 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd.h
+++ b/usr/src/cmd/smbsrv/smbd/smbd.h
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2022 Tintri by DDN, Inc. All rights reserved.
*/
#ifndef _SMBD_H
@@ -57,6 +57,8 @@ void smbd_set_secmode(int);
boolean_t smbd_online(void);
void smbd_online_wait(const char *);
void smbd_get_authconf(smb_kmod_cfg_t *);
+boolean_t smbd_logon_final(smb_token_t *, smb_inaddr_t *, char *, char *,
+ uint32_t);
void smbd_spool_start(void);
void smbd_spool_stop(void);
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_krb5ssp.c b/usr/src/cmd/smbsrv/smbd/smbd_krb5ssp.c
index ff0dff251b..b4a559bbb5 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_krb5ssp.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_krb5ssp.c
@@ -10,7 +10,7 @@
*/
/*
- * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2022 Tintri by DDN, Inc. All rights reserved.
*/
/*
@@ -102,10 +102,15 @@ smbd_krb5ssp_fini(authsvc_context_t *ctx)
free(be);
}
+static char *krb5ssp_def_username = "Unknown-Kerberos-User";
+static char *krb5ssp_def_domain = "Unknown-Domain";
+
/*
* Handle a Kerberos auth message.
*
- * State across messages is in ctx->ctx_backend
+ * State across messages is in ctx->ctx_backend.
+ *
+ * Equivalent to smbd_user_auth_logon().
*/
int
smbd_krb5ssp_work(authsvc_context_t *ctx)
@@ -119,12 +124,15 @@ smbd_krb5ssp_work(authsvc_context_t *ctx)
gss_OID mech_type = GSS_C_NULL_OID;
krb5_error_code kerr;
uint32_t status;
+ smb_token_t *token = NULL;
intok.length = ctx->ctx_ibodylen;
intok.value = ctx->ctx_ibodybuf;
bzero(&outtok, sizeof (gss_buffer_desc));
bzero(&namebuf, sizeof (gss_buffer_desc));
+ assert(be->be_username == NULL);
+
/* Do this early, for error message support. */
kerr = krb5_init_context(&be->be_kctx);
if (kerr != 0) {
@@ -158,7 +166,8 @@ smbd_krb5ssp_work(authsvc_context_t *ctx)
(int)mech_type, major, minor);
smbd_report(" krb5: %s",
krb5_get_error_message(be->be_kctx, minor));
- return (NT_STATUS_WRONG_PASSWORD);
+ status = NT_STATUS_WRONG_PASSWORD;
+ goto out;
}
switch (major) {
@@ -170,9 +179,11 @@ smbd_krb5ssp_work(authsvc_context_t *ctx)
/* becomes NT_STATUS_MORE_PROCESSING_REQUIRED */
return (0);
}
- return (NT_STATUS_WRONG_PASSWORD);
+ status = NT_STATUS_WRONG_PASSWORD;
+ goto out;
default:
- return (NT_STATUS_WRONG_PASSWORD);
+ status = NT_STATUS_WRONG_PASSWORD;
+ goto out;
}
/*
@@ -198,14 +209,15 @@ smbd_krb5ssp_work(authsvc_context_t *ctx)
status = get_authz_data_pac(be->be_gssctx,
&be->be_authz_pac);
if (status)
- return (status);
+ goto out;
kerr = krb5_pac_parse(be->be_kctx, be->be_authz_pac.value,
be->be_authz_pac.length, &be->be_kpac);
if (kerr) {
smbd_report("krb5ssp, krb5_pac_parse: %s",
krb5_get_error_message(be->be_kctx, kerr));
- return (NT_STATUS_UNSUCCESSFUL);
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
}
kerr = krb5_pac_get_buffer(be->be_kctx, be->be_kpac,
@@ -213,29 +225,60 @@ smbd_krb5ssp_work(authsvc_context_t *ctx)
if (kerr) {
smbd_report("krb5ssp, krb5_pac_get_buffer: %s",
krb5_get_error_message(be->be_kctx, kerr));
- return (NT_STATUS_UNSUCCESSFUL);
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
}
ctx->ctx_token = calloc(1, sizeof (smb_token_t));
- if (ctx->ctx_token == NULL)
- return (NT_STATUS_NO_MEMORY);
+ if (ctx->ctx_token == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
status = smb_decode_krb5_pac(ctx->ctx_token, be->be_pac.data,
be->be_pac.length);
if (status)
- return (status);
+ goto out;
status = get_ssnkey(ctx);
if (status)
- return (status);
+ goto out;
- if (!smb_token_setup_common(ctx->ctx_token))
- return (NT_STATUS_UNSUCCESSFUL);
+ if (!smb_token_setup_common(ctx->ctx_token)) {
+ status = NT_STATUS_UNSUCCESSFUL;
+ goto out;
+ }
/* Success! */
ctx->ctx_orawtype = LSA_MTYPE_ES_DONE;
- return (0);
+ status = 0;
+ token = ctx->ctx_token;
+
+ /*
+ * Before we return, audit successful and failed logons.
+ *
+ * Successful logons are audited using the username and domain
+ * contained in the ticket (where the domain comes from the PAC data).
+ *
+ * Failed logins use a 'default' domain. If we fail after obtaining
+ * the username in the ticket, we audit under that username.
+ *
+ * Prior to decoding the username, we only audit failures where we'll
+ * return NT_STATUS_WRONG_PASSWORD, so that we audit attempts with
+ * invalid (or forged) tickets. These records use a 'default' username;
+ * As such, they serve only to inform an administrator that
+ * a particular client used a bad ticket, but does not contain any
+ * information on the ticket itself.
+ *
+ * Once we have a username, we'll audit all failed authentications.
+ */
+out:
+ status = smbd_logon_final(token, &ctx->ctx_clinfo.lci_clnt_ipaddr,
+ (be->be_username != NULL) ? be->be_username : krb5ssp_def_username,
+ krb5ssp_def_domain, status);
+
+ return (status);
}
/*
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_logon.c b/usr/src/cmd/smbsrv/smbd/smbd_logon.c
index 69b32b2ec9..ba3de5ce93 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_logon.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_logon.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2022 Tintri by DDN, Inc. All rights reserved.
*/
#include <sys/types.h>
@@ -76,27 +76,17 @@ static smb_audit_t *smbd_audit_unlink(uint32_t);
/*
* Invoked at user logon due to SmbSessionSetupX. Authenticate the
- * user, start an audit session and audit the event.
+ * user.
*
- * On error, returns NULL, and status in user_info->lg_status
+ * On error, returns NULL, and status in user_info->lg_status.
+ *
+ * Equivalent to smbd_krb5ssp_work().
*/
smb_token_t *
smbd_user_auth_logon(smb_logon_t *user_info)
{
smb_token_t *token = NULL;
- smb_audit_t *entry;
- adt_session_data_t *ah = NULL;
- adt_event_data_t *event;
smb_logon_t tmp_user;
- au_tid_addr_t termid;
- char sidbuf[SMB_SID_STRSZ];
- char *username;
- char *domain;
- uid_t uid;
- gid_t gid;
- char *sid;
- int status;
- int retval;
char *p;
char *buf = NULL;
@@ -125,8 +115,10 @@ smbd_user_auth_logon(smb_logon_t *user_info)
if (tmp_user.lg_domain[0] == '\0' &&
(p = strchr(tmp_user.lg_e_username, '@')) != NULL) {
buf = strdup(tmp_user.lg_e_username);
- if (buf == NULL)
- goto errout;
+ if (buf == NULL) {
+ user_info->lg_status = NT_STATUS_NO_MEMORY;
+ return (NULL);
+ }
p = buf + (p - tmp_user.lg_e_username);
*p = '\0';
tmp_user.lg_e_domain = p + 1;
@@ -136,16 +128,49 @@ smbd_user_auth_logon(smb_logon_t *user_info)
}
token = smb_logon(&tmp_user);
- user_info->lg_status = tmp_user.lg_status;
+
+ if (token == NULL && tmp_user.lg_status == 0) /* should not happen */
+ user_info->lg_status = NT_STATUS_INTERNAL_ERROR;
+ else
+ user_info->lg_status = tmp_user.lg_status;
+
+ user_info->lg_status = smbd_logon_final(token,
+ &user_info->lg_clnt_ipaddr, tmp_user.lg_e_username,
+ tmp_user.lg_e_domain, user_info->lg_status);
+
+ free(buf);
+
+ if (user_info->lg_status != 0) {
+ smb_token_destroy(token);
+ token = NULL;
+ }
+ return (token);
+}
+
+/* Start an audit session and audit the event. */
+static boolean_t
+smbd_logon_audit(smb_token_t *token, smb_inaddr_t *ipaddr, char *username,
+ char *domain)
+{
+ smb_audit_t *entry;
+ adt_session_data_t *ah = NULL;
+ adt_event_data_t *event;
+ au_tid_addr_t termid;
+ char sidbuf[SMB_SID_STRSZ];
+ uid_t uid;
+ gid_t gid;
+ char *sid;
+ int status;
+ int retval;
+
+ assert(username != NULL);
+ assert(domain != NULL);
if (token == NULL) {
- if (user_info->lg_status == 0) /* should not happen */
- user_info->lg_status = NT_STATUS_INTERNAL_ERROR;
uid = ADT_NO_ATTRIB;
gid = ADT_NO_ATTRIB;
sid = NT_NULL_SIDSTR;
- username = tmp_user.lg_e_username;
- domain = tmp_user.lg_e_domain;
+ /* use the 'default' username and domain we were given */
status = ADT_FAILURE;
retval = ADT_FAIL_VALUE_AUTH;
} else {
@@ -161,25 +186,23 @@ smbd_user_auth_logon(smb_logon_t *user_info)
if (adt_start_session(&ah, NULL, 0)) {
syslog(LOG_AUTH | LOG_ALERT, "adt_start_session: %m");
- user_info->lg_status = NT_STATUS_AUDIT_FAILED;
goto errout;
}
if ((event = adt_alloc_event(ah, ADT_smbd_session)) == NULL) {
syslog(LOG_AUTH | LOG_ALERT,
"adt_alloc_event(ADT_smbd_session): %m");
- user_info->lg_status = NT_STATUS_AUDIT_FAILED;
goto errout;
}
(void) memset(&termid, 0, sizeof (au_tid_addr_t));
- termid.at_port = user_info->lg_local_port;
+ termid.at_port = IPPORT_SMB;
- if (user_info->lg_clnt_ipaddr.a_family == AF_INET) {
- termid.at_addr[0] = user_info->lg_clnt_ipaddr.a_ipv4;
+ if (ipaddr->a_family == AF_INET) {
+ termid.at_addr[0] = ipaddr->a_ipv4;
termid.at_type = AU_IPv4;
} else {
- bcopy(&user_info->lg_clnt_ipaddr.a_ip, termid.at_addr,
+ bcopy(&ipaddr->a_ip, termid.at_addr,
sizeof (in6_addr_t));
termid.at_type = AU_IPv6;
}
@@ -188,7 +211,6 @@ smbd_user_auth_logon(smb_logon_t *user_info)
if (adt_set_user(ah, uid, gid, uid, gid, NULL, ADT_NEW)) {
syslog(LOG_AUTH | LOG_ALERT, "adt_set_user: %m");
adt_free_event(event);
- user_info->lg_status = NT_STATUS_AUDIT_FAILED;
goto errout;
}
@@ -204,8 +226,6 @@ smbd_user_auth_logon(smb_logon_t *user_info)
if (token) {
if ((entry = malloc(sizeof (smb_audit_t))) == NULL) {
syslog(LOG_ERR, "smbd_user_auth_logon: %m");
- user_info->lg_status =
- NT_STATUS_INSUFFICIENT_RESOURCES;
goto errout;
}
@@ -215,22 +235,37 @@ smbd_user_auth_logon(smb_logon_t *user_info)
entry->sa_username = strdup(username);
entry->sa_domain = strdup(domain);
- smb_autohome_add(token);
smbd_audit_link(entry);
token->tkn_audit_sid = entry->sa_audit_sid;
-
- user_info->lg_status = NT_STATUS_SUCCESS;
}
- free(buf);
-
- return (token);
-
+ return (B_TRUE);
errout:
- free(buf);
(void) adt_end_session(ah);
- smb_token_destroy(token);
- return (NULL);
+ return (B_FALSE);
+}
+
+/*
+ * Handles all of the work needed to be done after SMB authentication,
+ * regardless of the auth flavor (Kerberos or NTLM).
+ *
+ * This should return the original status to the caller, unless something
+ * here causes us to turn what would be a success into a failure
+ * (or we decide we should override the original error for some reason).
+ */
+uint32_t
+smbd_logon_final(smb_token_t *token, smb_inaddr_t *ipaddr, char *username,
+ char *domain, uint32_t status)
+{
+ assert(token != NULL || status != 0);
+
+ if (!smbd_logon_audit(token, ipaddr, username, domain) && status == 0)
+ return (NT_STATUS_AUDIT_FAILED);
+
+ if (status == 0)
+ smb_autohome_add(token);
+
+ return (status);
}
/*
@@ -258,9 +293,11 @@ smbd_user_nonauth_logon(uint32_t audit_sid)
}
/*
- * Invoked at user logoff due to SmbLogoffX. If this is the final
+ * Invoked at user logoff due to SMB Logoff. If this is the final
* logoff for this user on the session, audit the event and terminate
* the audit session.
+ *
+ * This is called to logoff both NTLMSSP and KRB5SSP authentications.
*/
void
smbd_user_auth_logoff(uint32_t audit_sid)
diff --git a/usr/src/tools/quick/make-smbsrv b/usr/src/tools/quick/make-smbsrv
index f4c93ea0ee..b04ab47721 100755
--- a/usr/src/tools/quick/make-smbsrv
+++ b/usr/src/tools/quick/make-smbsrv
@@ -11,7 +11,7 @@
#
#
-# Copyright 2020 Tintri by DDN, Inc. All rights reserved.
+# Copyright 2022 Tintri by DDN, Inc. All rights reserved.
#
# Use normal make (not dmake) by default.
@@ -262,7 +262,7 @@ do
# We build these libraries (to the proto area), so we need to
# build the mdb modules for all dependent libraries too.
- for lib in libfksmbsrv libmlsvc libcmdutils libavl
+ for lib in libfksmbsrv libmlsvc list libavl
do
(cd $SRC/cmd/mdb/$x/$a/$lib && $make $1 )