9d1478
From a8611e205bfe7b7538523ec492069987f5d7de64 Mon Sep 17 00:00:00 2001
9d1478
From: Alexander Bokovoy <abokovoy@redhat.com>
9d1478
Date: Wed, 8 Apr 2020 15:00:38 +0300
9d1478
Subject: [PATCH] CVE-2020-1722: prevent use of too long passwords
9d1478
9d1478
NIST SP 800-63-3B sets a recommendation to have password length upper bound limited in A.2:
9d1478
9d1478
https://pages.nist.gov/800-63-3/sp800-63b.html#appA
9d1478
9d1478
	Users should be encouraged to make their passwords as lengthy as they
9d1478
	want, within reason. Since the size of a hashed password is independent
9d1478
	of its length, there is no reason not to permit the use of lengthy
9d1478
	passwords (or pass phrases) if the user wishes. Extremely long passwords
9d1478
	(perhaps megabytes in length) could conceivably require excessive
9d1478
	processing time to hash, so it is reasonable to have some limit.
9d1478
9d1478
FreeIPA already applied 256 characters limit for non-random passwords
9d1478
set through ipa-getkeytab tool. The limit was not, however, enforced in
9d1478
other places.
9d1478
9d1478
MIT Kerberos limits the length of the password to 1024 characters in its
9d1478
tools. However, these tools (kpasswd and 'cpw' command of kadmin) do not
9d1478
differentiate between a password larger than 1024 and a password of 1024
9d1478
characters. As a result, longer passwords are silently cut off.
9d1478
9d1478
To prevent silent cut off for user passwords, use limit of 1000
9d1478
characters.
9d1478
9d1478
Thus, this patch enforces common limit of 1000 characters everywhere:
9d1478
 - LDAP-based password changes
9d1478
   - LDAP password change control
9d1478
   - LDAP ADD and MOD operations on clear-text userPassword
9d1478
   - Keytab setting with ipa-getkeytab
9d1478
 - Kerberos password setting and changing
9d1478
9d1478
Fixes: https://pagure.io/freeipa/issue/8268
9d1478
9d1478
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
9d1478
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
9d1478
Reviewed-by: Simo Sorce <ssorce@redhat.com>
9d1478
Reviewed-By: Simo Sorce <ssorce@redhat.com>
9d1478
---
9d1478
 client/ipa-getkeytab.c                        | 19 ++++-
9d1478
 client/man/ipa-getkeytab.1                    |  2 +-
9d1478
 daemons/ipa-kdb/ipa_kdb_passwords.c           |  6 ++
9d1478
 .../ipa-slapi-plugins/ipa-pwd-extop/common.c  |  9 +++
9d1478
 .../ipa-pwd-extop/ipa_pwd_extop.c             | 13 +++
9d1478
 .../ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h  |  1 +
9d1478
 .../ipa-slapi-plugins/ipa-pwd-extop/prepost.c | 29 ++++++-
9d1478
 ipatests/test_integration/test_commands.py    | 79 +++++++++++++++++++
9d1478
 util/ipa_krb5.c                               | 18 +++++
9d1478
 util/ipa_krb5.h                               |  3 +
9d1478
 10 files changed, 171 insertions(+), 8 deletions(-)
9d1478
9d1478
diff --git a/client/ipa-getkeytab.c b/client/ipa-getkeytab.c
9d1478
index 8a5e98bed1947344247f9d6146e595d5f7f7a963..b174093d3762f8a6bfa27045bed393c2cd422fe0 100644
9d1478
--- a/client/ipa-getkeytab.c
9d1478
+++ b/client/ipa-getkeytab.c
9d1478
@@ -633,6 +633,11 @@ done:
9d1478
  * set match=true to enforce that the two entered passwords match.
9d1478
  *
9d1478
  * To prompt for an existing password provide prompt1 and set match=false.
9d1478
+ *
9d1478
+ * Implementation details:
9d1478
+ * krb5_prompter_posix() does not differentiate between too long entry or
9d1478
+ * an entry exactly the size of a buffer. Thus, allocate a bigger buffer
9d1478
+ * and do the check for a too long password afterwards.
9d1478
  */
9d1478
 static char *ask_password(krb5_context krbctx, char *prompt1, char *prompt2,
9d1478
                           bool match)
9d1478
@@ -640,8 +645,10 @@ static char *ask_password(krb5_context krbctx, char *prompt1, char *prompt2,
9d1478
     krb5_prompt ap_prompts[2];
9d1478
     krb5_data k5d_pw0;
9d1478
     krb5_data k5d_pw1;
9d1478
-    char pw0[256];
9d1478
-    char pw1[256];
9d1478
+#define MAX(a,b) (((a)>(b))?(a):(b))
9d1478
+#define PWD_BUFFER_SIZE MAX((IPAPWD_PASSWORD_MAX_LEN + 2), 1024)
9d1478
+    char pw0[PWD_BUFFER_SIZE];
9d1478
+    char pw1[PWD_BUFFER_SIZE];
9d1478
     char *password;
9d1478
     int num_prompts = match ? 2:1;
9d1478
 
9d1478
@@ -664,7 +671,12 @@ static char *ask_password(krb5_context krbctx, char *prompt1, char *prompt2,
9d1478
                 num_prompts, ap_prompts);
9d1478
 
9d1478
     if (match && (strcmp(pw0, pw1))) {
9d1478
-        fprintf(stderr, _("Passwords do not match!"));
9d1478
+        fprintf(stderr, _("Passwords do not match!\n"));
9d1478
+        return NULL;
9d1478
+    }
9d1478
+
9d1478
+    if (k5d_pw0.length > IPAPWD_PASSWORD_MAX_LEN) {
9d1478
+        fprintf(stderr, "%s\n", ipapwd_password_max_len_errmsg);
9d1478
         return NULL;
9d1478
     }
9d1478
 
9d1478
@@ -1017,6 +1029,7 @@ int main(int argc, const char *argv[])
9d1478
             }
9d1478
 
9d1478
             fprintf(stderr, _("Failed to create key material\n"));
9d1478
+            free_keys_contents(krbctx, &keys);
9d1478
             exit(8);
9d1478
         }
9d1478
 
9d1478
diff --git a/client/man/ipa-getkeytab.1 b/client/man/ipa-getkeytab.1
9d1478
index 6e7fdf39ee4e28772365edafd4c7e86d0c37d343..21ba651c4ac78d09bc57d498b38591fdbfd1d151 100644
9d1478
--- a/client/man/ipa-getkeytab.1
9d1478
+++ b/client/man/ipa-getkeytab.1
9d1478
@@ -95,7 +95,7 @@ DES cbc mode with RSA\-MD5
9d1478
 DES cbc mode with RSA\-MD4
9d1478
 .TP
9d1478
 \fB\-P, \-\-password\fR
9d1478
-Use this password for the key instead of one randomly generated.
9d1478
+Use this password for the key instead of one randomly generated. The length of the password is limited by 1024 characters. Note that MIT Kerberos also limits passwords entered through kpasswd and kadmin commands to the same length.
9d1478
 .TP
9d1478
 \fB\-D, \-\-binddn\fR
9d1478
 The LDAP DN to bind as when retrieving a keytab without Kerberos credentials. Generally used with the \fB\-w\fR or \fB\-W\fR options.
9d1478
diff --git a/daemons/ipa-kdb/ipa_kdb_passwords.c b/daemons/ipa-kdb/ipa_kdb_passwords.c
9d1478
index a3d4fe2436da60d081040754780d3e815acb1473..9362f4305d9973004a8c890540b5fa1622de772b 100644
9d1478
--- a/daemons/ipa-kdb/ipa_kdb_passwords.c
9d1478
+++ b/daemons/ipa-kdb/ipa_kdb_passwords.c
9d1478
@@ -80,6 +80,12 @@ static krb5_error_code ipadb_check_pw_policy(krb5_context context,
9d1478
         return EINVAL;
9d1478
     }
9d1478
 
9d1478
+    if (strlen(passwd) > IPAPWD_PASSWORD_MAX_LEN) {
9d1478
+        krb5_set_error_message(context, E2BIG, "%s",
9d1478
+                               ipapwd_password_max_len_errmsg);
9d1478
+        return E2BIG;
9d1478
+    }
9d1478
+
9d1478
     ied->passwd = strdup(passwd);
9d1478
     if (!ied->passwd) {
9d1478
         return ENOMEM;
9d1478
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/common.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/common.c
9d1478
index ba5c54e58e9b0b5dcc657d88c530c237e321495c..716b71333050f1d05063289f9890918b86ddb108 100644
9d1478
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/common.c
9d1478
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/common.c
9d1478
@@ -1087,3 +1087,12 @@ void free_ipapwd_krbcfg(struct ipapwd_krbcfg **cfg)
9d1478
     *cfg = NULL;
9d1478
 };
9d1478
 
9d1478
+int ipapwd_check_max_pwd_len(size_t len, char **errMesg) {
9d1478
+    if (len > IPAPWD_PASSWORD_MAX_LEN) {
9d1478
+        LOG("%s\n", ipapwd_password_max_len_errmsg);
9d1478
+        *errMesg = ipapwd_password_max_len_errmsg;
9d1478
+        return LDAP_CONSTRAINT_VIOLATION;
9d1478
+    }
9d1478
+    return 0;
9d1478
+}
9d1478
+
9d1478
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
9d1478
index f92706810d875cc6c7d8bc7a676c13ecc5d50e54..be413742cd2d54ab8bc7c51e6600b3dbbd26cec7 100644
9d1478
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
9d1478
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
9d1478
@@ -318,6 +318,11 @@ parse_req_done:
9d1478
 		goto free_and_return;
9d1478
 	}
9d1478
 
9d1478
+        rc = ipapwd_check_max_pwd_len(strlen(newPasswd), &errMesg);
9d1478
+        if (rc) {
9d1478
+            goto free_and_return;
9d1478
+        }
9d1478
+
9d1478
 	if (oldPasswd == NULL || *oldPasswd == '\0') {
9d1478
 		/* If user is authenticated, they already gave their password during
9d1478
 		the bind operation (or used sasl or client cert auth or OS creds) */
9d1478
@@ -1661,6 +1666,14 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
9d1478
 
9d1478
     } else {
9d1478
 
9d1478
+        if (password != NULL) {
9d1478
+            /* if password was passed-in, check its length */
9d1478
+            rc = ipapwd_check_max_pwd_len(strlen(password), &err_msg);
9d1478
+            if (rc) {
9d1478
+                goto free_and_return;
9d1478
+            }
9d1478
+	}
9d1478
+
9d1478
         /* check if we are allowed to *write* keys */
9d1478
         acl_ok = is_allowed_to_access_attr(pb, bind_dn, target_entry,
9d1478
                                            WRITEKEYS_OP_CHECK, NULL,
9d1478
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h
9d1478
index 31c76b3f1a3854a5126bf6c7bbb9bf7b3bcf02e7..5a49fa7e6c787f15b641da794ec5ee3e7a525292 100644
9d1478
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h
9d1478
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipapwd.h
9d1478
@@ -133,6 +133,7 @@ int ipapwd_set_extradata(const char *dn,
9d1478
                          time_t unixtime);
9d1478
 void ipapwd_free_slapi_value_array(Slapi_Value ***svals);
9d1478
 void free_ipapwd_krbcfg(struct ipapwd_krbcfg **cfg);
9d1478
+int ipapwd_check_max_pwd_len(size_t len, char **errMesg);
9d1478
 
9d1478
 /* from encoding.c */
9d1478
 struct ipapwd_keyset {
9d1478
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
9d1478
index 001f615ecdb87ac62fe237d5d9a932f0292c2e24..04cd2b10f3ba4375e6a278afe87cbd9d257d528f 100644
9d1478
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
9d1478
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c
9d1478
@@ -278,6 +278,10 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
9d1478
                 rc = LDAP_CONSTRAINT_VIOLATION;
9d1478
                 slapi_ch_free_string(&userpw);
9d1478
             } else {
9d1478
+                rc = ipapwd_check_max_pwd_len(strlen(userpw_clear), &errMesg);
9d1478
+                if (rc) {
9d1478
+                    goto done;
9d1478
+                }
9d1478
                 userpw = slapi_ch_strdup(userpw_clear);
9d1478
             }
9d1478
 
9d1478
@@ -560,6 +564,11 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
9d1478
                 goto done;
9d1478
             }
9d1478
             bv = lmod->mod_bvalues[0];
9d1478
+
9d1478
+            rc = ipapwd_check_max_pwd_len(bv->bv_len, &errMesg);
9d1478
+            if (rc) {
9d1478
+                goto done;
9d1478
+            }
9d1478
             slapi_ch_free_string(&unhashedpw);
9d1478
             unhashedpw = slapi_ch_malloc(bv->bv_len+1);
9d1478
             if (!unhashedpw) {
9d1478
@@ -782,7 +791,12 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
9d1478
     if (! unhashedpw && (gen_krb_keys || is_smb || is_ipant)) {
9d1478
         if ((userpw != NULL) && ('{' == userpw[0])) {
9d1478
             if (0 == strncasecmp(userpw, "{CLEAR}", strlen("{CLEAR}"))) {
9d1478
-                unhashedpw = slapi_ch_strdup(&userpw[strlen("{CLEAR}")]);
9d1478
+                const char *userpw_clear = &userpw[strlen("{CLEAR}")];
9d1478
+                rc = ipapwd_check_max_pwd_len(strlen(userpw_clear), &errMesg);
9d1478
+                if (rc) {
9d1478
+                    goto done;
9d1478
+                }
9d1478
+                unhashedpw = slapi_ch_strdup(userpw_clear);
9d1478
                 if (NULL == unhashedpw) {
9d1478
                     LOG_OOM();
9d1478
                     rc = LDAP_OPERATIONS_ERROR;
9d1478
@@ -1416,6 +1430,8 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
9d1478
     time_t expire_time;
9d1478
     char *principal_expire = NULL;
9d1478
     struct tm expire_tm;
9d1478
+    int rc = LDAP_INVALID_CREDENTIALS;
9d1478
+    char *errMesg = NULL;
9d1478
 
9d1478
     /* get BIND parameters */
9d1478
     ret |= slapi_pblock_get(pb, SLAPI_BIND_TARGET_SDN, &target_sdn);
9d1478
@@ -1477,8 +1493,14 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
9d1478
         goto invalid_creds;
9d1478
 
9d1478
     /* Ensure that there is a password. */
9d1478
-    if (credentials->bv_len == 0)
9d1478
+    if (credentials->bv_len == 0) {
9d1478
         goto invalid_creds;
9d1478
+    } else {
9d1478
+        rc = ipapwd_check_max_pwd_len(credentials->bv_len, &errMesg);
9d1478
+        if (rc) {
9d1478
+            goto invalid_creds;
9d1478
+        }
9d1478
+    }
9d1478
 
9d1478
     /* Authenticate the user. */
9d1478
     ret = ipapwd_authenticate(dn, entry, credentials);
9d1478
@@ -1502,8 +1524,7 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
9d1478
 invalid_creds:
9d1478
     slapi_entry_free(entry);
9d1478
     slapi_sdn_free(&sdn;;
9d1478
-    slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS,
9d1478
-                           NULL, NULL, 0, NULL);
9d1478
+    slapi_send_ldap_result(pb, rc, NULL, errMesg, 0, NULL);
9d1478
     return 1;
9d1478
 }
9d1478
 
9d1478
diff --git a/ipatests/test_integration/test_commands.py b/ipatests/test_integration/test_commands.py
9d1478
index a14a324ec2db26400aa67d2fc61f9c30b9b1d045..715a1f1a8f4105a470cc6f205a6bb9bc9db030e0 100644
9d1478
--- a/ipatests/test_integration/test_commands.py
9d1478
+++ b/ipatests/test_integration/test_commands.py
9d1478
@@ -33,6 +33,7 @@ from ipatests.test_integration.base import IntegrationTest
9d1478
 from ipatests.pytest_ipa.integration import tasks
9d1478
 from ipaplatform.tasks import tasks as platform_tasks
9d1478
 from ipatests.pytest_ipa.integration.create_external_ca import ExternalCA
9d1478
+from ipapython.ipautil import ipa_generate_password
9d1478
 
9d1478
 logger = logging.getLogger(__name__)
9d1478
 
9d1478
@@ -337,6 +338,84 @@ class TestIPACommand(IntegrationTest):
9d1478
         except CalledProcessError:
9d1478
             pytest.fail("Password change failed when it should not")
9d1478
 
9d1478
+    def test_huge_password(self):
9d1478
+        user = 'toolonguser'
9d1478
+        hostname = 'toolong.{}'.format(self.master.domain.name)
9d1478
+        huge_password = ipa_generate_password(min_len=1536)
9d1478
+        original_passwd = 'Secret123'
9d1478
+        master = self.master
9d1478
+        base_dn = str(master.domain.basedn)  # pylint: disable=no-member
9d1478
+
9d1478
+        # Create a user with a password that is too long
9d1478
+        tasks.kinit_admin(master)
9d1478
+        add_password_stdin_text = "{pwd}\n{pwd}".format(pwd=huge_password)
9d1478
+        result = master.run_command(['ipa', 'user-add', user,
9d1478
+                                     '--first', user,
9d1478
+                                     '--last', user,
9d1478
+                                     '--password'],
9d1478
+                                    stdin_text=add_password_stdin_text,
9d1478
+                                    raiseonerr=False)
9d1478
+        assert result.returncode != 0
9d1478
+
9d1478
+        # Try again with a normal password
9d1478
+        add_password_stdin_text = "{pwd}\n{pwd}".format(pwd=original_passwd)
9d1478
+        master.run_command(['ipa', 'user-add', user,
9d1478
+                            '--first', user,
9d1478
+                            '--last', user,
9d1478
+                            '--password'],
9d1478
+                           stdin_text=add_password_stdin_text)
9d1478
+
9d1478
+        # kinit as that user in order to modify the pwd
9d1478
+        user_kinit_stdin_text = "{old}\n%{new}\n%{new}\n".format(
9d1478
+            old=original_passwd,
9d1478
+            new=original_passwd)
9d1478
+        master.run_command(['kinit', user], stdin_text=user_kinit_stdin_text)
9d1478
+        # sleep 1 sec (krblastpwdchange and krbpasswordexpiration have at most
9d1478
+        # a 1s precision)
9d1478
+        time.sleep(1)
9d1478
+        # perform ldapmodify on userpassword as dir mgr
9d1478
+        entry_ldif = textwrap.dedent("""
9d1478
+            dn: uid={user},cn=users,cn=accounts,{base_dn}
9d1478
+            changetype: modify
9d1478
+            replace: userpassword
9d1478
+            userpassword: {new_passwd}
9d1478
+        """).format(
9d1478
+            user=user,
9d1478
+            base_dn=base_dn,
9d1478
+            new_passwd=huge_password)
9d1478
+
9d1478
+        result = tasks.ldapmodify_dm(master, entry_ldif, raiseonerr=False)
9d1478
+        assert result.returncode != 0
9d1478
+
9d1478
+        # ask_password in ipa-getkeytab will complain about too long password
9d1478
+        keytab_file = os.path.join(self.master.config.test_dir,
9d1478
+                                   'user.keytab')
9d1478
+        password_stdin_text = "{pwd}\n{pwd}".format(pwd=huge_password)
9d1478
+        result = self.master.run_command(['ipa-getkeytab',
9d1478
+                                          '-p', user,
9d1478
+                                          '-P',
9d1478
+                                          '-k', keytab_file,
9d1478
+                                          '-s', self.master.hostname],
9d1478
+                                         stdin_text=password_stdin_text,
9d1478
+                                         raiseonerr=False)
9d1478
+        assert result.returncode != 0
9d1478
+        assert "clear-text password is too long" in result.stderr_text
9d1478
+
9d1478
+        # Create a host with a user-set OTP that is too long
9d1478
+        tasks.kinit_admin(master)
9d1478
+        result = master.run_command(['ipa', 'host-add', '--force',
9d1478
+                                     hostname,
9d1478
+                                     '--password', huge_password],
9d1478
+                                    raiseonerr=False)
9d1478
+        assert result.returncode != 0
9d1478
+
9d1478
+        # Try again with a valid password
9d1478
+        result = master.run_command(['ipa', 'host-add', '--force',
9d1478
+                                     hostname,
9d1478
+                                     '--password', original_passwd],
9d1478
+                                    raiseonerr=False)
9d1478
+        assert result.returncode == 0
9d1478
+
9d1478
     def test_change_selinuxusermaporder(self):
9d1478
         """
9d1478
         An update file meant to ensure a more sane default was
9d1478
diff --git a/util/ipa_krb5.c b/util/ipa_krb5.c
9d1478
index c09c3daa505655f2e5292a79c03683faa75ad244..1ba6d25eecb27935ffb14923015f08745aad20fe 100644
9d1478
--- a/util/ipa_krb5.c
9d1478
+++ b/util/ipa_krb5.c
9d1478
@@ -31,6 +31,13 @@
9d1478
 
9d1478
 #include "ipa_krb5.h"
9d1478
 
9d1478
+#define TOSTR(x) STR(x)
9d1478
+#define STR(x) #x
9d1478
+const char *ipapwd_password_max_len_errmsg = \
9d1478
+    "clear-text password is too long (max " \
9d1478
+    TOSTR(IPAPWD_PASSWORD_MAX_LEN) \
9d1478
+    " chars)!";
9d1478
+
9d1478
 /* Salt types */
9d1478
 #define KRB5P_SALT_SIZE 16
9d1478
 
9d1478
@@ -125,6 +132,13 @@ krb5_error_code ipa_krb5_generate_key_data(krb5_context krbctx,
9d1478
     int num_keys;
9d1478
     int i;
9d1478
 
9d1478
+    if ((pwd.data != NULL) && (pwd.length > IPAPWD_PASSWORD_MAX_LEN)) {
9d1478
+        kerr = E2BIG;
9d1478
+        krb5_set_error_message(krbctx, kerr, "%s",
9d1478
+                               ipapwd_password_max_len_errmsg);
9d1478
+        return kerr;
9d1478
+    }
9d1478
+
9d1478
     num_keys = num_encsalts;
9d1478
     keys = calloc(num_keys, sizeof(krb5_key_data));
9d1478
     if (!keys) {
9d1478
@@ -970,6 +984,10 @@ int create_keys(krb5_context krbctx,
9d1478
     if (password) {
9d1478
         key_password.data = password;
9d1478
         key_password.length = strlen(password);
9d1478
+        if (key_password.length > IPAPWD_PASSWORD_MAX_LEN) {
9d1478
+            *err_msg = _("Password is too long!\n");
9d1478
+            return 0;
9d1478
+        }
9d1478
 
9d1478
         realm = krb5_princ_realm(krbctx, princ);
9d1478
     }
9d1478
diff --git a/util/ipa_krb5.h b/util/ipa_krb5.h
9d1478
index b039c1a7f3d0bc215376f8f1dd2ac93e75a0c626..8392a85b6740ece1ba7085a4733ea0f2f6b1fe64 100644
9d1478
--- a/util/ipa_krb5.h
9d1478
+++ b/util/ipa_krb5.h
9d1478
@@ -30,6 +30,9 @@ struct keys_container {
9d1478
 #define KEYTAB_RET_OID "2.16.840.1.113730.3.8.10.2"
9d1478
 #define KEYTAB_GET_OID "2.16.840.1.113730.3.8.10.5"
9d1478
 
9d1478
+#define IPAPWD_PASSWORD_MAX_LEN 1000
9d1478
+extern const char *ipapwd_password_max_len_errmsg;
9d1478
+
9d1478
 int krb5_klog_syslog(int, const char *, ...);
9d1478
 
9d1478
 void
9d1478
-- 
9d1478
2.25.2
9d1478