summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2011-10-10 15:42:11 -0400
committerSimo Sorce <ssorce@redhat.com>2011-10-13 11:35:06 -0400
commit789b560a5786b02bd210f90c5b75b18b3ca609b3 (patch)
tree4931c49497e1667b71af681376952db38d312d5e
parentae655c0425cb8e921dbe24752e1af768840b962b (diff)
downloadfreeipa-789b560a5786b02bd210f90c5b75b18b3ca609b3.tar.gz
freeipa-789b560a5786b02bd210f90c5b75b18b3ca609b3.tar.xz
freeipa-789b560a5786b02bd210f90c5b75b18b3ca609b3.zip
Add support for generating PAC for AS requests
-rw-r--r--daemons/configure.ac10
-rw-r--r--daemons/ipa-kdb/Makefile.am3
-rw-r--r--daemons/ipa-kdb/ipa_kdb.c2
-rw-r--r--daemons/ipa-kdb/ipa_kdb.h16
-rw-r--r--daemons/ipa-kdb/ipa_kdb_mspac.c230
5 files changed, 260 insertions, 1 deletions
diff --git a/daemons/configure.ac b/daemons/configure.ac
index e238d8b15..f89c50d62 100644
--- a/daemons/configure.ac
+++ b/daemons/configure.ac
@@ -227,6 +227,16 @@ if test "x$PYTHON" = "x" ; then
fi
dnl ---------------------------------------------------------------------------
+dnl Check for ndr_krb5pac
+dnl ---------------------------------------------------------------------------
+
+PKG_PROG_PKG_CONFIG()
+PKG_CHECK_MODULES([TALLOC], [talloc])
+PKG_CHECK_MODULES([TEVENT], [tevent])
+PKG_CHECK_MODULES([NDRPAC], [ndr_krb5pac])
+
+
+dnl ---------------------------------------------------------------------------
dnl - Set the data install directory since we don't use pkgdatadir
dnl ---------------------------------------------------------------------------
diff --git a/daemons/ipa-kdb/Makefile.am b/daemons/ipa-kdb/Makefile.am
index 036074f43..b29f60171 100644
--- a/daemons/ipa-kdb/Makefile.am
+++ b/daemons/ipa-kdb/Makefile.am
@@ -19,6 +19,7 @@ INCLUDES = \
$(KRB5_CFLAGS) \
$(SSL_CFLAGS) \
$(WARN_CFLAGS) \
+ $(NDRPAC_CFLAGS) \
$(NULL)
plugindir = $(libdir)/krb5/plugins/kdb
@@ -33,6 +34,7 @@ ipadb_la_SOURCES = \
ipa_kdb_passwords.c \
ipa_kdb_principals.c \
ipa_kdb_pwdpolicy.c \
+ ipa_kdb_mspac.c \
$(KRB5_UTIL_SRCS) \
$(NULL)
@@ -45,6 +47,7 @@ ipadb_la_LIBADD = \
$(KRB5_LIBS) \
$(SSL_LIBS) \
$(LDAP_LIBS) \
+ $(NDRPAC_LIBS) \
$(NULL)
dist_noinst_DATA = ipa_kdb.exports
diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c
index 880a7890b..1594d8316 100644
--- a/daemons/ipa-kdb/ipa_kdb.c
+++ b/daemons/ipa-kdb/ipa_kdb.c
@@ -445,7 +445,7 @@ kdb_vftabl kdb_function_table = {
NULL, /* promote_db */
NULL, /* decrypt_key_data */
NULL, /* encrypt_key_data */
- NULL, /* sign_authdata */
+ ipadb_sign_authdata, /* sign_authdata */
NULL, /* check_transited_realms */
NULL, /* check_policy_as */
NULL, /* check_policy_tgs */
diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h
index cfcaca649..d026656ac 100644
--- a/daemons/ipa-kdb/ipa_kdb.h
+++ b/daemons/ipa-kdb/ipa_kdb.h
@@ -182,3 +182,19 @@ krb5_error_code ipadb_get_pwd_expiration(krb5_context context,
krb5_db_entry *entry,
struct ipadb_e_data *ied,
time_t *expire_time);
+
+/* MS-PAC FUNCTIONS */
+
+krb5_error_code ipadb_sign_authdata(krb5_context context,
+ unsigned int flags,
+ krb5_const_principal client_princ,
+ krb5_db_entry *client,
+ krb5_db_entry *server,
+ krb5_db_entry *krbtgt,
+ krb5_keyblock *client_key,
+ krb5_keyblock *server_key,
+ krb5_keyblock *krbtgt_key,
+ krb5_keyblock *session_key,
+ krb5_timestamp authtime,
+ krb5_authdata **tgt_auth_data,
+ krb5_authdata ***signed_auth_data);
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
new file mode 100644
index 000000000..410f4306e
--- /dev/null
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
@@ -0,0 +1,230 @@
+/*
+ * MIT Kerberos KDC database backend for FreeIPA
+ *
+ * Authors: Simo Sorce <ssorce@redhat.com>
+ *
+ * Copyright (C) 2011 Simo Sorce, Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * This program is free software you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ipa_kdb.h"
+#include "gen_ndr/ndr_krb5pac.h"
+#include <krb5/krb5.h>
+#include <kdb.h>
+
+#define KRB5INT_PAC_SIGN_AVAILABLE 1
+
+#if KRB5INT_PAC_SIGN_AVAILABLE
+krb5_error_code
+krb5int_pac_sign(krb5_context context,
+ krb5_pac pac,
+ krb5_timestamp authtime,
+ krb5_const_principal principal,
+ const krb5_keyblock *server_key,
+ const krb5_keyblock *privsvr_key,
+ krb5_data *data);
+#define krb5_pac_sign krb5int_pac_sign
+#define KRB5_PAC_LOGON_INFO 1
+#endif
+
+
+#define EMPTY_LSA_STRING { 0, 0, NULL }
+const char simo[] = { 0x73, 0x00, 0x6a, 0x00, 0x6d, 0x00, 0x6f, 0x00 };
+const char ipa[] = { 0x6a, 0x00, 0x70, 0x00, 0x61, 0x00, 0x00, 0x00 };
+
+
+static krb5_error_code ipadb_get_pac(krb5_context context,
+ krb5_db_entry *client,
+ krb5_pac *pac)
+{
+ TALLOC_CTX *tmpctx;
+ DATA_BLOB pac_data;
+ krb5_data data;
+ struct netr_SamInfo3 info3;
+ struct dom_sid2 dom_sid;
+ union PAC_INFO pac_info;
+ krb5_error_code kerr;
+ enum ndr_err_code ndr_err;
+
+ memset(&info3, 0, sizeof(info3));
+ memset(&pac_info, 0, sizeof(pac_info));
+
+ tmpctx = talloc_new(NULL);
+ if (!tmpctx) {
+ return ENOMEM;
+ }
+
+ pac_info.logon_info.info = talloc_zero(tmpctx, struct PAC_LOGON_INFO);
+ if (!tmpctx) {
+ kerr = ENOMEM;
+ goto done;
+ }
+
+/* info3.base.last_logon
+ info3.base.last_logoff
+ info3.base.acct_expiry
+ info3.base.last_password_change
+ info3.base.allow_password_change
+ info3.base.force_password_change */
+ info3.base.account_name.length = sizeof(simo);
+ info3.base.account_name.size = sizeof(simo);
+ info3.base.account_name.string = simo;
+ info3.base.full_name.length = sizeof(simo);
+ info3.base.full_name.size = sizeof(simo);
+ info3.base.full_name.string = simo;
+/* info3.base.logon_script
+ info3.base.profile_path
+ info3.base.home_directory
+ info3.base.home_drive
+ info3.base.logon_count
+ info3.base.bad_password_count */
+ info3.base.rid = 1000;
+ info3.base.primary_gid = 1001;
+/* info3.base.groups */
+ info3.base.user_flags = 0;
+/* info3.base.key */
+ info3.base.logon_server.length = sizeof(ipa) - 2;
+ info3.base.logon_server.size = sizeof(ipa);
+ info3.base.logon_server.string = ipa;
+ info3.base.domain.length = sizeof(ipa) - 2;
+ info3.base.domain.size = sizeof(ipa);
+ info3.base.domain.string = ipa;
+ dom_sid.sid_rev_num = 1;
+ dom_sid.num_auths = 4;
+ dom_sid.id_auth[5] = 5;
+ dom_sid.sub_auths[0] = 15;
+ dom_sid.sub_auths[1] = 1;
+ dom_sid.sub_auths[2] = 2;
+ dom_sid.sub_auths[3] = 3;
+ info3.base.domain_sid = &dom_sid;
+/* info3.base.LMSessKey */
+ info3.base.acct_flags = 0;
+
+ pac_info.logon_info.info->info3 = info3;
+
+ ndr_err = ndr_push_union_blob(&pac_data, tmpctx, &pac_info,
+ PAC_TYPE_LOGON_INFO,
+ (ndr_push_flags_fn_t)ndr_push_PAC_INFO);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ kerr = KRB5_KDB_INTERNAL_ERROR;
+ goto done;
+ }
+
+ kerr = krb5_pac_init(context, pac);
+ if (kerr) {
+ goto done;
+ }
+
+ data.magic = KV5M_DATA;
+ data.data = (char *)pac_data.data;
+ data.length = pac_data.length;
+
+ kerr = krb5_pac_add_buffer(context, *pac, KRB5_PAC_LOGON_INFO, &data);
+
+done:
+ talloc_free(tmpctx);
+ return kerr;
+}
+
+
+krb5_error_code ipadb_sign_authdata(krb5_context context,
+ unsigned int flags,
+ krb5_const_principal client_princ,
+ krb5_db_entry *client,
+ krb5_db_entry *server,
+ krb5_db_entry *krbtgt,
+ krb5_keyblock *client_key,
+ krb5_keyblock *server_key,
+ krb5_keyblock *krbtgt_key,
+ krb5_keyblock *session_key,
+ krb5_timestamp authtime,
+ krb5_authdata **tgt_auth_data,
+ krb5_authdata ***signed_auth_data)
+{
+ krb5_const_principal ks_client_princ;
+ krb5_authdata *authdata[2] = { NULL, NULL };
+ krb5_authdata ad;
+ krb5_boolean is_as_req;
+ krb5_error_code kerr;
+ krb5_pac pac = NULL;
+ krb5_data pac_data;
+
+ /* Prefer canonicalised name from client entry */
+ if (client != NULL) {
+ ks_client_princ = client->princ;
+ } else {
+ ks_client_princ = client_princ;
+ }
+
+ is_as_req = ((flags & KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY) != 0);
+
+ if (is_as_req && (flags & KRB5_KDB_FLAG_INCLUDE_PAC)) {
+
+ kerr = ipadb_get_pac(context, client, &pac);
+ if (kerr != 0) {
+ goto done;
+ }
+ }
+#if 0
+ if (!is_as_req) {
+ code = ks_verify_pac(context, flags, ks_client_princ, client,
+ server_key, krbtgt_key, authtime,
+ tgt_auth_data, &pac);
+ if (code != 0) {
+ goto done;
+ }
+ }
+
+ if (pac == NULL && client != NULL) {
+
+ code = ks_get_pac(context, client, &pac);
+ if (code != 0) {
+ goto done;
+ }
+ }
+#endif
+ if (pac == NULL) {
+ kerr = KRB5_KDB_DBTYPE_NOSUP;
+ goto done;
+ }
+
+ kerr = krb5_pac_sign(context, pac, authtime, ks_client_princ,
+ server_key, krbtgt_key, &pac_data);
+ if (kerr != 0) {
+ goto done;
+ }
+
+ /* put in signed data */
+ ad.magic = KV5M_AUTHDATA;
+ ad.ad_type = KRB5_AUTHDATA_WIN2K_PAC;
+ ad.contents = (krb5_octet *)pac_data.data;
+ ad.length = pac_data.length;
+ authdata[0] = &ad;
+
+ kerr = krb5_encode_authdata_container(context,
+ KRB5_AUTHDATA_IF_RELEVANT,
+ &authdata,
+ signed_auth_data);
+ if (kerr != 0) {
+ goto done;
+ }
+
+ kerr = 0;
+
+done:
+ krb5_pac_free(context, pac);
+ return kerr;
+}