--- auth/auth_util.c.orig 2014-06-16 03:26:53.548570930 -0700 +++ auth/auth_util.c 2014-06-17 02:02:30.598976494 -0700 @@ -1243,7 +1243,7 @@ NTSTATUS make_server_info_info3(TALLOC_C const char *sent_nt_username, const char *domain, struct auth_serversupplied_info **server_info, - struct netr_SamInfo3 *info3) + const struct netr_SamInfo3 *info3) { static const char zeros[16] = {0, }; --- auth/proto.h.orig 2014-06-17 06:51:21.123964446 -0700 +++ auth/proto.h 2014-06-18 03:43:43.450779722 -0700 @@ -32,6 +32,7 @@ #ifndef _AUTH_PROTO_H_ #define _AUTH_PROTO_H_ +#include "../librpc/gen_ndr/krb5pac.h" /* The following definitions come from auth/auth.c */ @@ -169,7 +170,7 @@ NTSTATUS make_server_info_info3(TALLOC_C const char *sent_nt_username, const char *domain, struct auth_serversupplied_info **server_info, - struct netr_SamInfo3 *info3); + const struct netr_SamInfo3 *info3); struct wbcAuthUserInfo; NTSTATUS make_server_info_wbcAuthUserInfo(TALLOC_CTX *mem_ctx, const char *sent_nt_username, @@ -219,13 +220,16 @@ NTSTATUS serverinfo_to_SamInfo6(struct a uint8_t *pipe_session_key, size_t pipe_session_key_len, struct netr_SamInfo6 *sam6); +NTSTATUS create_info3_from_pac_logon_info(TALLOC_CTX *mem_ctx, + const struct PAC_LOGON_INFO *logon_info, + struct netr_SamInfo3 **pp_info3); NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx, struct samu *samu, const char *login_server, struct netr_SamInfo3 **_info3, struct extra_auth_info *extra); struct netr_SamInfo3 *copy_netr_SamInfo3(TALLOC_CTX *mem_ctx, - struct netr_SamInfo3 *orig); + const struct netr_SamInfo3 *orig); struct netr_SamInfo3 *wbcAuthUserInfo_to_netr_SamInfo3(TALLOC_CTX *mem_ctx, const struct wbcAuthUserInfo *info); @@ -297,7 +301,7 @@ NTSTATUS make_server_info_krb5(TALLOC_CT char *ntdomain, char *username, struct passwd *pw, - struct PAC_LOGON_INFO *logon_info, + const struct netr_SamInfo3 *info3, bool mapped_to_guest, struct auth_serversupplied_info **server_info); --- auth/server_info.c.orig 2014-06-16 03:26:47.669543008 -0700 +++ auth/server_info.c 2014-06-18 03:47:07.642722553 -0700 @@ -291,6 +291,82 @@ static NTSTATUS group_sids_to_info3(stru return NT_STATUS_OK; } +/* + * Merge resource SIDs, if any, into the passed in info3 structure. + */ + +static NTSTATUS merge_resource_sids(const struct PAC_LOGON_INFO *logon_info, + struct netr_SamInfo3 *info3) +{ + uint32_t i = 0; + + if (!(logon_info->info3.base.user_flags & NETLOGON_RESOURCE_GROUPS)) { + return NT_STATUS_OK; + } + + /* + * If there are any resource groups (SID Compression) add + * them to the extra sids portion of the info3 in the PAC. + * + * This makes the info3 look like it would if we got the info + * from the DC rather than the PAC. + */ + + /* + * Construct a SID for each RID in the list and then append it + * to the info3. + */ + for (i = 0; i < logon_info->res_groups.count; i++) { + NTSTATUS status; + struct dom_sid new_sid; + uint32_t attributes = logon_info->res_groups.rids[i].attributes; + + sid_compose(&new_sid, + logon_info->res_group_dom_sid, + logon_info->res_groups.rids[i].rid); + + DEBUG(10, ("Adding SID %s to extra SIDS\n", + sid_string_dbg(&new_sid))); + + status = append_netr_SidAttr(info3, &info3->sids, + &info3->sidcount, + &new_sid, + attributes); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("failed to append SID %s to extra SIDS: %s\n", + sid_string_dbg(&new_sid), + nt_errstr(status))); + return status; + } + } + + return NT_STATUS_OK; +} + +/* + * Create a copy of an info3 struct from the struct PAC_LOGON_INFO, + * then merge resource SIDs, if any, into it. If successful return + * the created info3 struct. + */ + +NTSTATUS create_info3_from_pac_logon_info(TALLOC_CTX *mem_ctx, + const struct PAC_LOGON_INFO *logon_info, + struct netr_SamInfo3 **pp_info3) +{ + NTSTATUS status; + struct netr_SamInfo3 *info3 = copy_netr_SamInfo3(mem_ctx, + &logon_info->info3); + if (info3 == NULL) { + return NT_STATUS_NO_MEMORY; + } + status = merge_resource_sids(logon_info, info3); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(info3); + return status; + } + *pp_info3 = info3; + return NT_STATUS_OK; +} #define RET_NOMEM(ptr) do { \ if (!ptr) { \ @@ -485,7 +561,7 @@ NTSTATUS samu_to_SamInfo3(TALLOC_CTX *me } } while(0) struct netr_SamInfo3 *copy_netr_SamInfo3(TALLOC_CTX *mem_ctx, - struct netr_SamInfo3 *orig) + const struct netr_SamInfo3 *orig) { struct netr_SamInfo3 *info3; unsigned int i; --- auth/user_krb5.c.orig 2014-06-17 06:53:16.625499697 -0700 +++ auth/user_krb5.c 2014-06-17 06:53:02.469432096 -0700 @@ -184,7 +184,7 @@ NTSTATUS make_server_info_krb5(TALLOC_CT char *ntdomain, char *username, struct passwd *pw, - struct PAC_LOGON_INFO *logon_info, + const struct netr_SamInfo3 *info3, bool mapped_to_guest, struct auth_serversupplied_info **server_info) { @@ -198,14 +198,14 @@ NTSTATUS make_server_info_krb5(TALLOC_CT return status; } - } else if (logon_info) { + } else if (info3) { /* pass the unmapped username here since map_username() will be called again in make_server_info_info3() */ status = make_server_info_info3(mem_ctx, ntuser, ntdomain, server_info, - &logon_info->info3); + info3); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("make_server_info_info3 failed: %s!\n", nt_errstr(status))); @@ -285,7 +285,7 @@ NTSTATUS make_server_info_krb5(TALLOC_CT char *ntdomain, char *username, struct passwd *pw, - struct PAC_LOGON_INFO *logon_info, + const struct netr_SamInfo3 *info3, bool mapped_to_guest, struct auth_serversupplied_info **server_info) { --- rpc_server/dcesrv_gssapi.c.orig 2014-06-17 06:54:19.171788401 -0700 +++ rpc_server/dcesrv_gssapi.c 2014-06-17 06:54:08.827738249 -0700 @@ -194,7 +194,7 @@ NTSTATUS gssapi_server_get_user_info(str status = make_server_info_krb5(mem_ctx, ntuser, ntdomain, username, pw, - logon_info, is_guest, server_info); + &logon_info->info3, is_guest, server_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to map kerberos pac to server info (%s)\n", nt_errstr(status))); --- smbd/sesssetup.c.orig 2014-06-16 03:26:40.012508385 -0700 +++ smbd/sesssetup.c 2014-06-18 02:01:26.019454791 -0700 @@ -257,6 +257,7 @@ static void reply_spnego_kerberos(struct bool map_domainuser_to_guest = False; bool username_was_mapped; struct PAC_LOGON_INFO *logon_info = NULL; + struct netr_SamInfo3 *info3_copy = NULL; struct smbd_server_connection *sconn = req->sconn; char *principal; char *user; @@ -362,7 +363,18 @@ static void reply_spnego_kerberos(struct /* save the PAC data if we have it */ if (logon_info) { - netsamlogon_cache_store(user, &logon_info->info3); + ret = create_info3_from_pac_logon_info(mem_ctx, + logon_info, + &info3_copy); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(1, ("create_info3_from_pac_logon_info failed: %s\n", + nt_errstr(ret))); + data_blob_free(&ap_rep); + data_blob_free(&session_key); + TALLOC_FREE(mem_ctx); + return; + } + netsamlogon_cache_store(user, info3_copy); } /* setup the string used by %U */ @@ -373,7 +385,7 @@ static void reply_spnego_kerberos(struct ret = make_server_info_krb5(mem_ctx, user, domain, real_username, pw, - logon_info, map_domainuser_to_guest, + info3_copy, map_domainuser_to_guest, &server_info); if (!NT_STATUS_IS_OK(ret)) { DEBUG(1, ("make_server_info_krb5 failed!\n")); --- smbd/smb2_sesssetup.c.orig 2014-06-16 03:26:33.828479130 -0700 +++ smbd/smb2_sesssetup.c 2014-06-18 02:20:31.920741407 -0700 @@ -178,6 +178,7 @@ static NTSTATUS smbd_smb2_session_setup_ DATA_BLOB secblob_out = data_blob_null; uint8 tok_id[2]; struct PAC_LOGON_INFO *logon_info = NULL; + struct netr_SamInfo3 *info3_copy = NULL; char *principal = NULL; char *user = NULL; char *domain = NULL; @@ -220,7 +221,15 @@ static NTSTATUS smbd_smb2_session_setup_ /* save the PAC data if we have it */ if (logon_info) { - netsamlogon_cache_store(user, &logon_info->info3); + status = create_info3_from_pac_logon_info(smb2req, + logon_info, + &info3_copy); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("create_info3_from_pac_logon_info failed: %s\n", + nt_errstr(status))); + return status; + } + netsamlogon_cache_store(NULL, info3_copy); } /* setup the string used by %U */ @@ -231,7 +240,7 @@ static NTSTATUS smbd_smb2_session_setup_ status = make_server_info_krb5(session, user, domain, real_username, pw, - logon_info, map_domainuser_to_guest, + info3_copy, map_domainuser_to_guest, &session->session_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("smb2: make_server_info_krb5 failed\n")); --- winbindd/winbindd_pam.c.orig 2014-06-16 03:26:26.748446612 -0700 +++ winbindd/winbindd_pam.c 2014-06-18 02:09:56.176807472 -0700 @@ -546,6 +546,7 @@ static NTSTATUS winbindd_raw_kerberos_lo time_t time_offset = 0; const char *user_ccache_file; struct PAC_LOGON_INFO *logon_info = NULL; + struct netr_SamInfo3 *info3_copy = NULL; *info3 = NULL; @@ -623,8 +624,18 @@ static NTSTATUS winbindd_raw_kerberos_lo if (!NT_STATUS_IS_OK(result)) { goto failed; } + if (logon_info) { + result = create_info3_from_pac_logon_info(mem_ctx, + logon_info, + &info3_copy); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(1, ("create_info3_from_pac_logon_info failed: %s\n", + nt_errstr(result))); + goto failed; + } + } - *info3 = &logon_info->info3; + *info3 = info3_copy; DEBUG(10,("winbindd_raw_kerberos_login: winbindd validated ticket of %s\n", principal_s));