From cbef7b5e10f4477d9f2e648ac6c654eef1165b82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 24 Sep 2014 22:16:20 +0200 Subject: [PATCH 1/4] s3-net: add "net ads enctypes {list,set,delete}". MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Andreas Schneider Reviewed-by: Stefan Metzmacher --- source3/utils/net_ads.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 308 insertions(+) diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 8b8e719..5f18bf4 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -2860,6 +2860,306 @@ int net_ads_kerberos(struct net_context *c, int argc, const char **argv) return net_run_function(c, argc, argv, "net ads kerberos", func); } +static int net_ads_enctype_lookup_account(struct net_context *c, + ADS_STRUCT *ads, + const char *account, + LDAPMessage **res, + const char **enctype_str) +{ + const char *filter; + const char *attrs[] = { + "msDS-SupportedEncryptionTypes", + NULL + }; + int count; + int ret = -1; + ADS_STATUS status; + + filter = talloc_asprintf(c, "(&(objectclass=user)(sAMAccountName=%s))", + account); + if (filter == NULL) { + goto done; + } + + status = ads_search(ads, res, filter, attrs); + if (!ADS_ERR_OK(status)) { + d_printf(_("no account found with filter: %s\n"), filter); + goto done; + } + + count = ads_count_replies(ads, *res); + switch (count) { + case 1: + break; + case 0: + d_printf(_("no account found with filter: %s\n"), filter); + goto done; + default: + d_printf(_("multiple accounts found with filter: %s\n"), filter); + goto done; + } + + if (enctype_str) { + *enctype_str = ads_pull_string(ads, c, *res, + "msDS-SupportedEncryptionTypes"); + if (*enctype_str == NULL) { + d_printf(_("no msDS-SupportedEncryptionTypes attribute found\n")); + goto done; + } + } + + ret = 0; + done: + return ret; +} + +static void net_ads_enctype_dump_enctypes(const char *username, + const char *enctype_str) +{ + int enctypes; + + d_printf(_("'%s' uses \"msDS-SupportedEncryptionTypes\":\n"), username); + + enctypes = atoi(enctype_str); + + printf("[%s] 0x%08x DES-CBC-CRC\n", + enctypes & ENC_CRC32 ? "X" : " ", + ENC_CRC32); + printf("[%s] 0x%08x DES-CBC-MD5\n", + enctypes & ENC_RSA_MD5 ? "X" : " ", + ENC_RSA_MD5); + printf("[%s] 0x%08x RC4-HMAC\n", + enctypes & ENC_RC4_HMAC_MD5 ? "X" : " ", + ENC_RC4_HMAC_MD5); + printf("[%s] 0x%08x AES128-CTS-HMAC-SHA1-96\n", + enctypes & ENC_HMAC_SHA1_96_AES128 ? "X" : " ", + ENC_HMAC_SHA1_96_AES128); + printf("[%s] 0x%08x AES256-CTS-HMAC-SHA1-96\n", + enctypes & ENC_HMAC_SHA1_96_AES256 ? "X" : " ", + ENC_HMAC_SHA1_96_AES256); +} + +static int net_ads_enctypes_list(struct net_context *c, int argc, const char **argv) +{ + int ret = -1; + ADS_STATUS status; + ADS_STRUCT *ads = NULL; + LDAPMessage *res = NULL; + const char *str = NULL; + + if (c->display_usage || (argc < 1)) { + d_printf( "%s\n" + "net ads enctypes list\n" + " %s\n", + _("Usage:"), + _("List supported enctypes")); + return 0; + } + + status = ads_startup(c, false, &ads); + if (!ADS_ERR_OK(status)) { + printf("startup failed\n"); + return ret; + } + + ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str); + if (ret) { + goto done; + } + + net_ads_enctype_dump_enctypes(argv[0], str); + + ret = 0; + done: + ads_msgfree(ads, res); + ads_destroy(&ads); + + return ret; +} + +static int net_ads_enctypes_set(struct net_context *c, int argc, const char **argv) +{ + int ret = -1; + ADS_STATUS status; + ADS_STRUCT *ads; + LDAPMessage *res = NULL; + const char *etype_list_str; + const char *dn; + ADS_MODLIST mods; + uint32_t etype_list; + const char *str; + + if (c->display_usage || argc < 1) { + d_printf( "%s\n" + "net ads enctypes set [enctypes]\n" + " %s\n", + _("Usage:"), + _("Set supported enctypes")); + return 0; + } + + status = ads_startup(c, false, &ads); + if (!ADS_ERR_OK(status)) { + printf("startup failed\n"); + return ret; + } + + ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL); + if (ret) { + goto done; + } + + dn = ads_get_dn(ads, c, res); + if (dn == NULL) { + goto done; + } + + etype_list = ENC_CRC32 | ENC_RSA_MD5 | ENC_RC4_HMAC_MD5; +#ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96 + etype_list |= ENC_HMAC_SHA1_96_AES128; +#endif +#ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96 + etype_list |= ENC_HMAC_SHA1_96_AES256; +#endif + + if (argv[1] != NULL) { + sscanf(argv[1], "%i", &etype_list); + } + + etype_list_str = talloc_asprintf(c, "%d", etype_list); + if (!etype_list_str) { + goto done; + } + + mods = ads_init_mods(c); + if (!mods) { + goto done; + } + + status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes", + etype_list_str); + if (!ADS_ERR_OK(status)) { + goto done; + } + + status = ads_gen_mod(ads, dn, mods); + if (!ADS_ERR_OK(status)) { + d_printf(_("failed to add msDS-SupportedEncryptionTypes: %s\n"), + ads_errstr(status)); + goto done; + } + + ads_msgfree(ads, res); + + ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, &str); + if (ret) { + goto done; + } + + net_ads_enctype_dump_enctypes(argv[0], str); + + ret = 0; + done: + ads_msgfree(ads, res); + ads_destroy(&ads); + + return ret; +} + +static int net_ads_enctypes_delete(struct net_context *c, int argc, const char **argv) +{ + int ret = -1; + ADS_STATUS status; + ADS_STRUCT *ads; + LDAPMessage *res = NULL; + const char *dn; + ADS_MODLIST mods; + + if (c->display_usage || argc < 1) { + d_printf( "%s\n" + "net ads enctypes delete \n" + " %s\n", + _("Usage:"), + _("Delete supported enctypes")); + return 0; + } + + status = ads_startup(c, false, &ads); + if (!ADS_ERR_OK(status)) { + printf("startup failed\n"); + return ret; + } + + ret = net_ads_enctype_lookup_account(c, ads, argv[0], &res, NULL); + if (ret) { + goto done; + } + + dn = ads_get_dn(ads, c, res); + if (dn == NULL) { + goto done; + } + + mods = ads_init_mods(c); + if (!mods) { + goto done; + } + + status = ads_mod_str(c, &mods, "msDS-SupportedEncryptionTypes", NULL); + if (!ADS_ERR_OK(status)) { + goto done; + } + + status = ads_gen_mod(ads, dn, mods); + if (!ADS_ERR_OK(status)) { + d_printf(_("failed to remove msDS-SupportedEncryptionTypes: %s\n"), + ads_errstr(status)); + goto done; + } + + ret = 0; + + done: + ads_msgfree(ads, res); + ads_destroy(&ads); + return ret; +} + +static int net_ads_enctypes(struct net_context *c, int argc, const char **argv) +{ + struct functable func[] = { + { + "list", + net_ads_enctypes_list, + NET_TRANSPORT_ADS, + N_("List the supported encryption types"), + N_("net ads enctypes list\n" + " List the supported encryption types") + }, + { + "set", + net_ads_enctypes_set, + NET_TRANSPORT_ADS, + N_("Set the supported encryption types"), + N_("net ads enctypes set\n" + " Set the supported encryption types") + }, + { + "delete", + net_ads_enctypes_delete, + NET_TRANSPORT_ADS, + N_("Delete the supported encryption types"), + N_("net ads enctypes delete\n" + " Delete the supported encryption types") + }, + + {NULL, NULL, 0, NULL, NULL} + }; + + return net_run_function(c, argc, argv, "net ads enctypes", func); +} + + int net_ads(struct net_context *c, int argc, const char **argv) { struct functable func[] = { @@ -3015,6 +3315,14 @@ int net_ads(struct net_context *c, int argc, const char **argv) N_("net ads kerberos\n" " Manage kerberos keytab") }, + { + "enctypes", + net_ads_enctypes, + NET_TRANSPORT_ADS, + N_("List/modify supported encryption types"), + N_("net ads enctypes\n" + " List/modify enctypes") + }, {NULL, NULL, 0, NULL, NULL} }; -- 1.9.3 From a19f1e51bd7d48b238ad22ec9e27af53dfa5bf44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Wed, 24 Sep 2014 23:36:19 +0200 Subject: [PATCH 2/4] s3-net: add manpage documentation for "net ads enctypes". MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Andreas Schneider Reviewed-by: Stefan Metzmacher --- docs-xml/manpages/net.8.xml | 53 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/docs-xml/manpages/net.8.xml b/docs-xml/manpages/net.8.xml index f39b420..9e982e3 100644 --- a/docs-xml/manpages/net.8.xml +++ b/docs-xml/manpages/net.8.xml @@ -1339,6 +1339,59 @@ to show in the result. + ADS ENCTYPES + + + List, modify or delete the value of the "msDS-SupportedEncryptionTypes" attribute of an account in AD. + + + + This attribute allows to control which Kerberos encryption types are used for the generation of initial and service tickets. The value consists of an integer bitmask with the following values: + + +0x00000001 DES-CBC-CRC +0x00000002 DES-CBC-MD5 +0x00000004 RC4-HMAC +0x00000008 AES128-CTS-HMAC-SHA1-96 +0x00000010 AES256-CTS-HMAC-SHA1-96 + + + + + ADS ENCTYPES LIST <replaceable><ACCOUNTNAME></replaceable> + + + List the value of the "msDS-SupportedEncryptionTypes" attribute of a given account. + + +Example: net ads enctypes list Computername + + + + + ADS ENCTYPES SET <replaceable><ACCOUNTNAME></replaceable> <replaceable>[enctypes]</replaceable> + + + Set the value of the "msDS-SupportedEncryptionTypes" attribute of the LDAP object of ACCOUNTNAME to a given value. If the value is ommitted, the value is set to 31 which enables all the currently supported encryption types. + + +Example: net ads enctypes set Computername 24 + + + + + ADS ENCTYPES DELETE <replaceable><ACCOUNTNAME></replaceable> + + + Deletes the "msDS-SupportedEncryptionTypes" attribute of the LDAP object of ACCOUNTNAME. + + +Example: net ads enctypes set Computername 24 + + + + + SAM CREATEBUILTINGROUP <NAME> -- 1.9.3 From 0f42d123afde57ee74d89bdc742185cef718cf0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 23 Nov 2012 12:34:27 +0100 Subject: [PATCH 3/4] s3-libnet: set list of allowed krb5 encryption types in AD >= 2008. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Guenther Signed-off-by: Günther Deschner Reviewed-by: Andreas Schneider Reviewed-by: Stefan Metzmacher --- source3/libnet/libnet_join.c | 65 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/source3/libnet/libnet_join.c b/source3/libnet/libnet_join.c index 381a59c..e70e11a 100644 --- a/source3/libnet/libnet_join.c +++ b/source3/libnet/libnet_join.c @@ -605,6 +605,52 @@ static ADS_STATUS libnet_join_set_os_attributes(TALLOC_CTX *mem_ctx, /**************************************************************** ****************************************************************/ +static ADS_STATUS libnet_join_set_etypes(TALLOC_CTX *mem_ctx, + struct libnet_JoinCtx *r) +{ + ADS_STATUS status; + ADS_MODLIST mods; + uint32_t etype_list = ENC_CRC32 | ENC_RSA_MD5 | ENC_RC4_HMAC_MD5; + const char *etype_list_str; + +#ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96 + etype_list |= ENC_HMAC_SHA1_96_AES128; +#endif +#ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96 + etype_list |= ENC_HMAC_SHA1_96_AES256; +#endif + + etype_list_str = talloc_asprintf(mem_ctx, "%d", etype_list); + if (!etype_list_str) { + return ADS_ERROR(LDAP_NO_MEMORY); + } + + /* Find our DN */ + + status = libnet_join_find_machine_acct(mem_ctx, r); + if (!ADS_ERR_OK(status)) { + return status; + } + + /* now do the mods */ + + mods = ads_init_mods(mem_ctx); + if (!mods) { + return ADS_ERROR(LDAP_NO_MEMORY); + } + + status = ads_mod_str(mem_ctx, &mods, "msDS-SupportedEncryptionTypes", + etype_list_str); + if (!ADS_ERR_OK(status)) { + return status; + } + + return ads_gen_mod(r->in.ads, r->out.dn, mods); +} + +/**************************************************************** +****************************************************************/ + static bool libnet_join_create_keytab(TALLOC_CTX *mem_ctx, struct libnet_JoinCtx *r) { @@ -679,6 +725,7 @@ static ADS_STATUS libnet_join_post_processing_ads(TALLOC_CTX *mem_ctx, struct libnet_JoinCtx *r) { ADS_STATUS status; + uint32_t func_level = 0; if (!r->in.ads) { status = libnet_join_connect_ads(mem_ctx, r); @@ -713,6 +760,24 @@ static ADS_STATUS libnet_join_post_processing_ads(TALLOC_CTX *mem_ctx, return status; } + status = ads_domain_func_level(r->in.ads, &func_level); + if (!ADS_ERR_OK(status)) { + libnet_join_set_error_string(mem_ctx, r, + "failed to query domain controller functional level: %s", + ads_errstr(status)); + return status; + } + + if (func_level >= DS_DOMAIN_FUNCTION_2008) { + status = libnet_join_set_etypes(mem_ctx, r); + if (!ADS_ERR_OK(status)) { + libnet_join_set_error_string(mem_ctx, r, + "failed to set machine kerberos encryption types: %s", + ads_errstr(status)); + return status; + } + } + if (!libnet_join_derive_salting_principal(mem_ctx, r)) { return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); } -- 1.9.3 From adb206481ac56c8f438e70f7b9e986aeba9586b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Deschner?= Date: Fri, 26 Sep 2014 21:06:38 +0200 Subject: [PATCH 4/4] s4-auth/kerberos: fix salting principal, make sure hostname is lowercase. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found at MS interop event while working on AES kerberos key support. Guenther Signed-off-by: Günther Deschner Reviewed-by: Andrew Bartlett --- source4/auth/kerberos/srv_keytab.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source4/auth/kerberos/srv_keytab.c b/source4/auth/kerberos/srv_keytab.c index d81e27d..3baba14 100644 --- a/source4/auth/kerberos/srv_keytab.c +++ b/source4/auth/kerberos/srv_keytab.c @@ -143,7 +143,7 @@ static krb5_error_code salt_principal(TALLOC_CTX *parent_ctx, return ENOMEM; } - machine_username = talloc_strdup(tmp_ctx, samAccountName); + machine_username = strlower_talloc(tmp_ctx, samAccountName); if (!machine_username) { *error_string = "Cannot duplicate samAccountName"; talloc_free(tmp_ctx); -- 1.9.3 From d423e8b759af2e0a7cdce39d3f7a6c8d9c1764b4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Jun 2014 22:49:29 -0700 Subject: [PATCH 1/5] s3: auth: Add some const to the struct netr_SamInfo3 * arguments of copy_netr_SamInfo3() and make_server_info_info3() Both functions only read from the struct netr_SamInfo3 * argument. Signed-off-by: Jeremy Allison Reviewed-by: Richard Sharpe Reviewed-by: Simo Sorce Conflicts: source3/auth/proto.h source3/auth/server_info.c --- source3/auth/auth_util.c | 2 +- source3/auth/proto.h | 4 ++-- source3/auth/server_info.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index ceaa706..afa78ec 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -1369,7 +1369,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, 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, }; diff --git a/source3/auth/proto.h b/source3/auth/proto.h index 76661fc..6ec206e 100644 --- a/source3/auth/proto.h +++ b/source3/auth/proto.h @@ -232,7 +232,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, 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, @@ -287,7 +287,7 @@ NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx, const struct passwd *pwd, struct netr_SamInfo3 **pinfo3); 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); diff --git a/source3/auth/server_info.c b/source3/auth/server_info.c index d2b7d6e..066b9a8 100644 --- a/source3/auth/server_info.c +++ b/source3/auth/server_info.c @@ -445,7 +445,7 @@ NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx, } } 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; -- 1.9.3 From cab0cda9df0bb0eda2d7957c0bb8dbcb51ba7ef7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Jun 2014 22:54:45 -0700 Subject: [PATCH 2/5] s3: auth: Change make_server_info_info3() to take a const struct netr_SamInfo3 pointer instead of a struct PAC_LOGON_INFO. make_server_info_info3() only reads from the info3 pointer. Signed-off-by: Jeremy Allison Reviewed-by: Richard Sharpe Reviewed-by: Simo Sorce --- source3/auth/auth_generic.c | 2 +- source3/auth/proto.h | 2 +- source3/auth/user_krb5.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c index a2ba4e3..2880bc9 100644 --- a/source3/auth/auth_generic.c +++ b/source3/auth/auth_generic.c @@ -112,7 +112,7 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, status = make_session_info_krb5(mem_ctx, ntuser, ntdomain, username, pw, - logon_info, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */, + &logon_info->info3, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */, session_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to map kerberos pac to server info (%s)\n", diff --git a/source3/auth/proto.h b/source3/auth/proto.h index 6ec206e..75d1097 100644 --- a/source3/auth/proto.h +++ b/source3/auth/proto.h @@ -357,7 +357,7 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, char *ntdomain, char *username, struct passwd *pw, - struct PAC_LOGON_INFO *logon_info, + const struct netr_SamInfo3 *info3, bool mapped_to_guest, bool username_was_mapped, DATA_BLOB *session_key, struct auth_session_info **session_info); diff --git a/source3/auth/user_krb5.c b/source3/auth/user_krb5.c index 974a8aa..0a538b4 100644 --- a/source3/auth/user_krb5.c +++ b/source3/auth/user_krb5.c @@ -186,7 +186,7 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, char *ntdomain, char *username, struct passwd *pw, - struct PAC_LOGON_INFO *logon_info, + const struct netr_SamInfo3 *info3, bool mapped_to_guest, bool username_was_mapped, DATA_BLOB *session_key, struct auth_session_info **session_info) @@ -202,14 +202,14 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, 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))); @@ -299,7 +299,7 @@ NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx, char *ntdomain, char *username, struct passwd *pw, - struct PAC_LOGON_INFO *logon_info, + const struct netr_SamInfo3 *info3, bool mapped_to_guest, bool username_was_mapped, DATA_BLOB *session_key, struct auth_session_info **session_info) -- 1.9.3 From 102335441aaa7967367abcc5690fe7229807546a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Jun 2014 23:11:58 -0700 Subject: [PATCH 3/5] s3: auth: Add create_info3_from_pac_logon_info() to create a new info3 and merge resource group SIDs into it. Originally written by Richard Sharpe Richard Sharpe . Signed-off-by: Jeremy Allison Reviewed-by: Richard Sharpe Reviewed-by: Simo Sorce --- source3/auth/proto.h | 3 ++ source3/auth/server_info.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/source3/auth/proto.h b/source3/auth/proto.h index 75d1097..cc51698 100644 --- a/source3/auth/proto.h +++ b/source3/auth/proto.h @@ -281,6 +281,9 @@ NTSTATUS serverinfo_to_SamInfo3(const struct auth_serversupplied_info *server_in struct netr_SamInfo3 *sam3); NTSTATUS serverinfo_to_SamInfo6(struct auth_serversupplied_info *server_info, 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, diff --git a/source3/auth/server_info.c b/source3/auth/server_info.c index 066b9a8..dc84794 100644 --- a/source3/auth/server_info.c +++ b/source3/auth/server_info.c @@ -252,6 +252,83 @@ static NTSTATUS group_sids_to_info3(struct netr_SamInfo3 *info3, 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) { \ TALLOC_FREE(info3); \ -- 1.9.3 From fda9cefd3d4a0808af67595631dd755d5b73aacf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Jun 2014 23:15:21 -0700 Subject: [PATCH 4/5] s3: auth: Change auth3_generate_session_info_pac() to use a copy of the info3 struct from the struct PAC_LOGON_INFO. Call create_info3_from_pac_logon_info() to add in any resource SIDs from the struct PAC_LOGON_INFO to the info3. Signed-off-by: Jeremy Allison Reviewed-by: Richard Sharpe Reviewed-by: Simo Sorce --- source3/auth/auth_generic.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c index 2880bc9..f841f0c 100644 --- a/source3/auth/auth_generic.c +++ b/source3/auth/auth_generic.c @@ -44,6 +44,7 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, { TALLOC_CTX *tmp_ctx; struct PAC_LOGON_INFO *logon_info = NULL; + struct netr_SamInfo3 *info3_copy = NULL; bool is_mapped; bool is_guest; char *ntuser; @@ -101,7 +102,13 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, /* save the PAC data if we have it */ if (logon_info) { - netsamlogon_cache_store(ntuser, &logon_info->info3); + status = create_info3_from_pac_logon_info(tmp_ctx, + logon_info, + &info3_copy); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + netsamlogon_cache_store(ntuser, info3_copy); } /* setup the string used by %U */ @@ -112,7 +119,7 @@ static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, status = make_session_info_krb5(mem_ctx, ntuser, ntdomain, username, pw, - &logon_info->info3, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */, + info3_copy, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */, session_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to map kerberos pac to server info (%s)\n", -- 1.9.3 From 9ed711f88685fc2d4860c9d6b7fa651bd2a52558 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 16 Jun 2014 23:27:35 -0700 Subject: [PATCH 5/5] s3: auth: Fix winbindd_pam_auth_pac_send() to create a new info3 and merge in resource groups from a trusted PAC. Based on a patch from Richard Sharpe . Signed-off-by: Jeremy Allison Reviewed-by: Richard Sharpe Reviewed-by: Simo Sorce Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Wed Jun 18 03:30:36 CEST 2014 on sn-devel-104 --- source3/winbindd/winbindd_pam.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index c356686..0f1ca28 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -2421,6 +2421,7 @@ NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state, struct winbindd_request *req = state->request; DATA_BLOB pac_blob; struct PAC_LOGON_INFO *logon_info = NULL; + struct netr_SamInfo3 *info3_copy = NULL; NTSTATUS result; pac_blob = data_blob_const(req->extra_data.data, req->extra_len); @@ -2434,7 +2435,13 @@ NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state, if (logon_info) { /* Signature verification succeeded, trust the PAC */ - netsamlogon_cache_store(NULL, &logon_info->info3); + result = create_info3_from_pac_logon_info(state->mem_ctx, + logon_info, + &info3_copy); + if (!NT_STATUS_IS_OK(result)) { + return result; + } + netsamlogon_cache_store(NULL, info3_copy); } else { /* Try without signature verification */ @@ -2446,9 +2453,22 @@ NTSTATUS winbindd_pam_auth_pac_send(struct winbindd_cli_state *state, nt_errstr(result))); return result; } + if (logon_info) { + /* + * Don't strictly need to copy here, + * but it makes it explicit we're + * returning a copy talloc'ed off + * the state->mem_ctx. + */ + info3_copy = copy_netr_SamInfo3(state->mem_ctx, + &logon_info->info3); + if (info3_copy == NULL) { + return NT_STATUS_NO_MEMORY; + } + } } - *info3 = &logon_info->info3; + *info3 = info3_copy; return NT_STATUS_OK; } -- 1.9.3