ipa/0003-ipa-kdb-Add-OTP-support.patch
Rob Crittenden 12216fc83f Add OTP patches and patch to fix 389-ds ccache
The OTP patches add basic support for TOTP and Radius.

The 389-ds patch sets KRB5CCNAME in /etc/sysconfig/dirsrv so it can
get a usable ccache.
2013-05-14 16:28:58 -04:00

188 lines
6.4 KiB
Diff

From 5b15278283d3be6d615c98963807facf34da31eb Mon Sep 17 00:00:00 2001
From: Nathaniel McCallum <npmccallum@redhat.com>
Date: Thu, 11 Apr 2013 13:50:42 -0400
Subject: [PATCH 3/6] ipa-kdb: Add OTP support
If OTP is enabled for a user, then:
1. Long-term keys are not provided to KDB
2. The user string 'otp' is defined to KDB
Since it is not secure to send radius configuration information
over krb5 user strings, we simply set the string to a known default
('[]') which enables the default configuration in the KDC.
https://fedorahosted.org/freeipa/ticket/3561
http://freeipa.org/page/V3/OTP
---
daemons/ipa-kdb/ipa_kdb.c | 38 +++++++++++++++++++++++++++++++++++-
daemons/ipa-kdb/ipa_kdb.h | 13 ++++++++++++
daemons/ipa-kdb/ipa_kdb_principals.c | 28 ++++++++++++++++++++++++++
3 files changed, 78 insertions(+), 1 deletion(-)
diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c
index e5c718e..8464264 100644
--- a/daemons/ipa-kdb/ipa_kdb.c
+++ b/daemons/ipa-kdb/ipa_kdb.c
@@ -173,9 +173,42 @@ done:
return base;
}
+static const struct {
+ const char *name;
+ enum ipadb_user_auth flag;
+} userauth_table[] = {
+ { "disabled", IPADB_USER_AUTH_DISABLED },
+ { "password", IPADB_USER_AUTH_PASSWORD },
+ { "radius", IPADB_USER_AUTH_RADIUS },
+ { "otp", IPADB_USER_AUTH_OTP },
+ { }
+};
+
+void ipadb_get_user_auth(LDAP *lcontext, LDAPMessage *le,
+ enum ipadb_user_auth *userauth)
+{
+ struct berval **vals;
+ int i, j;
+
+ *userauth = IPADB_USER_AUTH_EMPTY;
+ vals = ldap_get_values_len(lcontext, le, IPA_USER_AUTH_TYPE);
+ if (!vals)
+ return;
+
+ for (i = 0; vals[i]; i++) {
+ for (j = 0; userauth_table[j].name; j++) {
+ if (strcasecmp(vals[i]->bv_val, userauth_table[j].name) == 0) {
+ *userauth |= userauth_table[j].flag;
+ break;
+ }
+ }
+ }
+}
+
int ipadb_get_global_configs(struct ipadb_context *ipactx)
{
- char *attrs[] = { "ipaConfigString", IPA_KRB_AUTHZ_DATA_ATTR, NULL };
+ char *attrs[] = { "ipaConfigString", IPA_KRB_AUTHZ_DATA_ATTR,
+ IPA_USER_AUTH_TYPE, NULL };
struct berval **vals = NULL;
LDAPMessage *res = NULL;
LDAPMessage *first;
@@ -203,6 +236,9 @@ int ipadb_get_global_configs(struct ipadb_context *ipactx)
goto done;
}
+ /* Check for permitted authentication types. */
+ ipadb_get_user_auth(ipactx->lcontext, res, &ipactx->user_auth);
+
vals = ldap_get_values_len(ipactx->lcontext, first,
"ipaConfigString");
if (!vals || !vals[0]) {
diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h
index 9daaab8..54869d8 100644
--- a/daemons/ipa-kdb/ipa_kdb.h
+++ b/daemons/ipa-kdb/ipa_kdb.h
@@ -75,9 +75,18 @@
#define IPA_SETUP "ipa-setup-override-restrictions"
#define IPA_KRB_AUTHZ_DATA_ATTR "ipaKrbAuthzData"
+#define IPA_USER_AUTH_TYPE "ipaUserAuthType"
struct ipadb_mspac;
+enum ipadb_user_auth {
+ IPADB_USER_AUTH_EMPTY = 0,
+ IPADB_USER_AUTH_DISABLED = 1 << 0,
+ IPADB_USER_AUTH_PASSWORD = 1 << 1,
+ IPADB_USER_AUTH_RADIUS = 1 << 2,
+ IPADB_USER_AUTH_OTP = 1 << 3,
+};
+
struct ipadb_context {
char *uri;
char *base;
@@ -92,6 +101,7 @@ struct ipadb_context {
bool disable_last_success;
bool disable_lockout;
char **authz_data;
+ enum ipadb_user_auth user_auth;
};
#define IPA_E_DATA_MAGIC 0x0eda7a
@@ -259,3 +269,6 @@ void ipadb_audit_as_req(krb5_context kcontext,
krb5_timestamp authtime,
krb5_error_code error_code);
+/* AUTH METHODS */
+void ipadb_get_user_auth(LDAP *lcontext, LDAPMessage *le,
+ enum ipadb_user_auth *user_auth);
diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c
index 11c155e..3566e1e 100644
--- a/daemons/ipa-kdb/ipa_kdb_principals.c
+++ b/daemons/ipa-kdb/ipa_kdb_principals.c
@@ -64,6 +64,7 @@ static char *std_principal_attrs[] = {
"nsaccountlock",
"passwordHistory",
IPA_KRB_AUTHZ_DATA_ATTR,
+ IPA_USER_AUTH_TYPE,
"objectClass",
NULL
@@ -228,6 +229,9 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
krb5_db_entry **kentry,
uint32_t *polmask)
{
+ krb5_octet otp_string[] = {'o', 't', 'p', 0, '[', ']', 0 };
+ enum ipadb_user_auth user_ua = IPADB_USER_AUTH_EMPTY;
+ enum ipadb_user_auth *active_ua = &user_ua;
struct ipadb_context *ipactx;
LDAP *lcontext;
krb5_db_entry *entry;
@@ -262,6 +266,17 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
entry->magic = KRB5_KDB_MAGIC_NUMBER;
entry->len = KRB5_KDB_V1_BASE_LENGTH;
+ /* Get the user's user_auth settings. */
+ ipadb_get_user_auth(ipactx->lcontext, lentry, &user_ua);
+
+ /* TODO: Should we confirm the existence of ipatokenRadiusConfigLink in
+ * the case of RADIUS? Existence of a token for OTP? */
+
+ /* Determine which user_auth policy is active: user or global. */
+ if ((ipactx->user_auth & IPADB_USER_AUTH_DISABLED)
+ || user_ua == IPADB_USER_AUTH_EMPTY)
+ active_ua = &ipactx->user_auth;
+
/* ignore mask for now */
ret = ipadb_ldap_attr_to_int(lcontext, lentry,
@@ -393,6 +408,13 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
&res_key_data, &result, &mkvno);
switch (ret) {
case 0:
+ /* Only set a principal's key if password auth should be used. */
+ if ((*active_ua & ~IPADB_USER_AUTH_DISABLED) != IPADB_USER_AUTH_EMPTY
+ && !(*active_ua & IPADB_USER_AUTH_PASSWORD)) {
+ /* This is the same behavior as ENOENT below. */
+ break;
+ }
+
entry->key_data = res_key_data;
entry->n_key_data = result;
if (mkvno) {
@@ -515,6 +537,12 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
ied->authz_data = authz_data_list;
}
+ /* If enabled, set the otp user string, enabling otp. */
+ if ((*active_ua & (IPADB_USER_AUTH_RADIUS | IPADB_USER_AUTH_OTP)) &&
+ !(*active_ua & IPADB_USER_AUTH_DISABLED)) {
+ ret = ipadb_set_tl_data(entry, KRB5_TL_STRING_ATTRS,
+ sizeof(otp_string), otp_string);
+ }
kerr = 0;
--
1.8.2.1