summaryrefslogtreecommitdiffstats
path: root/daemons/ipa-kdb/ipa_kdb_mspac.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemons/ipa-kdb/ipa_kdb_mspac.c')
-rw-r--r--daemons/ipa-kdb/ipa_kdb_mspac.c230
1 files changed, 230 insertions, 0 deletions
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;
+}