diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/smbsrv/smbd/smbd.h | 4 | ||||
-rw-r--r-- | usr/src/cmd/smbsrv/smbd/smbd_krb5ssp.c | 73 | ||||
-rw-r--r-- | usr/src/cmd/smbsrv/smbd/smbd_logon.c | 121 | ||||
-rwxr-xr-x | usr/src/tools/quick/make-smbsrv | 4 |
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 ) |