ctrl->data = control;
return ctrl;
}
+
+ if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_POLICY_HINTS_NAME) == 0) {
+ const char *p = NULL;
+ int crit, val, ret;
+
+ p = &(control_strings[sizeof(LDB_CONTROL_POLICY_HINTS_NAME)]);
+ ret = sscanf(p, "%d:%d", &crit, &val);
+ if ((ret != 2) || (crit < 0) || (crit > 1)) {
+ ldb_set_errstring(ldb,
+ "invalid pwd_policy_hints control syntax\n"
+ " syntax: crit(b):flags(n)\n"
+ " note: b = boolean, n = number");
+ talloc_free(ctrl);
+ return NULL;
+ }
+
+ ctrl->oid = LDB_CONTROL_POLICY_HINTS_OID;
+ ctrl->critical = crit;
+ ctrl->data = talloc(ctrl, int);
+ *((int*)ctrl->data) = val;
+ return ctrl;
+ }
+
+ if (LDB_CONTROL_CMP(control_strings, LDB_CONTROL_POLICY_HINTS_DEPRECATED_NAME) == 0) {
+ const char *p = NULL;
+ int crit, val, ret;
+
+ p = &(control_strings[sizeof(LDB_CONTROL_POLICY_HINTS_DEPRECATED_NAME)]);
+ ret = sscanf(p, "%d:%d", &crit, &val);
+ if ((ret != 2) || (crit < 0) || (crit > 1)) {
+ ldb_set_errstring(ldb,
+ "invalid pwd_policy_hints control syntax\n"
+ " syntax: crit(b):flags(n)\n"
+ " note: b = boolean, n = number");
+ talloc_free(ctrl);
+ return NULL;
+ }
+
+ ctrl->oid = LDB_CONTROL_POLICY_HINTS_DEPRECATED_OID;
+ ctrl->critical = crit;
+ ctrl->data = talloc(ctrl, int);
+ *((int*)ctrl->data) = val;
+ return ctrl;
+ }
+
+
/*
* When no matching control has been found.
*/
*/
#define LDB_EXTENDED_WHOAMI_OID "1.3.6.1.4.1.4203.1.11.3"
+/**
+ OID used to enforce password history length constraints in password reset
+
+ If this is control as the value 0x1 on a password set operation,
+ the password history constraints in MS-SAMR 3.1.1.7.1 "General
+ Password Policy" apply as if this was a password change. This may
+ be used by Entra ID or Keycloak.
+
+ LDB_CONTROL_POLICY_HINTS_DEPRECATED_OID (below) does exactly the
+ same thing and seems to be more widely used in practice.
+*/
+#define LDB_CONTROL_POLICY_HINTS_OID "1.2.840.113556.1.4.2239"
+#define LDB_CONTROL_POLICY_HINTS_NAME "policy_hints"
+
+/**
+ Another OID used to enforce password history length constraints in password reset
+
+ This works just like LDB_CONTROL_POLICY_HINTS_OID (above): if the
+ control value is 0x1 on a password set operation, the password
+ history constraints in MS-SAMR 3.1.1.7.1 "General Password Policy"
+ apply as if this was a password change.
+
+ This is used by Entra ID in a password change.
+
+ It is also the OID for the ms-DS-Required-Domain-Behavior-Version
+ attribute), which is unlikely to cause confusion given the contexts.
+*/
+#define LDB_CONTROL_POLICY_HINTS_DEPRECATED_OID "1.2.840.113556.1.4.2066"
+#define LDB_CONTROL_POLICY_HINTS_DEPRECATED_NAME "policy_hints_deprecated"
+
struct ldb_sd_flags_control {
/*
* request the owner 0x00000001
return true;
}
+static bool decode_policy_hints_request(void *mem_ctx, DATA_BLOB in, void *_out)
+{
+ void **out = (void **)_out;
+ int *valp = NULL;
+ int val;
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
+ if (!data) {
+ return false;
+ }
+
+ if (!asn1_load(data, in)) {
+ return false;
+ }
+
+ if (!asn1_start_tag(data, ASN1_SEQUENCE(0))) {
+ return false;
+ }
+
+ if (!asn1_read_Integer(data, &val)) {
+ return false;
+ }
+
+ if (!asn1_end_tag(data)) {
+ return false;
+ }
+
+ valp = talloc(mem_ctx, int);
+ if (valp == NULL) {
+ return false;
+ }
+ *valp = val;
+ *out = valp;
+
+ return true;
+}
+
static bool encode_server_sort_response(void *mem_ctx, void *in, DATA_BLOB *out)
{
struct ldb_sort_resp_control *lsrc = talloc_get_type(in, struct ldb_sort_resp_control);
return true;
}
+
+
+static bool encode_policy_hints_request(void *mem_ctx, void *in, DATA_BLOB *out)
+{
+ int *val = talloc_get_type(in, int);
+ struct asn1_data *data = asn1_init(mem_ctx, ASN1_MAX_TREE_DEPTH);
+ if (!data) {
+ return false;
+ }
+
+ if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) {
+ return false;
+ }
+
+ if (!asn1_write_Integer(data, *val)) {
+ return false;
+ }
+
+ if (!asn1_pop_tag(data)) {
+ return false;
+ }
+
+ if (!asn1_extract_blob(data, mem_ctx, out)) {
+ return false;
+ }
+
+ talloc_free(data);
+
+ return true;
+}
+
+
+
+
static bool encode_flag_request(void *mem_ctx, void *in, DATA_BLOB *out)
{
if (in) {
{ LDB_CONTROL_RELAX_OID, decode_flag_request, encode_flag_request },
{ DSDB_OPENLDAP_DEREFERENCE_CONTROL, decode_openldap_dereference, encode_openldap_dereference },
{ LDB_CONTROL_VERIFY_NAME_OID, decode_verify_name_request, encode_verify_name_request },
+ { LDB_CONTROL_POLICY_HINTS_OID, decode_policy_hints_request, encode_policy_hints_request },
+ { LDB_CONTROL_POLICY_HINTS_DEPRECATED_OID, decode_policy_hints_request, encode_policy_hints_request },
/* the following are internal only, with a network
representation */