#define LDAP_CONTROL_DUPENT LDAP_CONTROL_DUPENT_REQUEST
#endif
+/* Control Requests and Response for password policies */
+
+#define LDAP_CONTROL_PASSWORDPOLICYREQUEST "1.3.6.1.4.1.42.2.27.8.5.1"
+#define LDAP_CONTROL_PASSWORDPOLICYRESPONSE "1.3.6.1.4.1.42.2.27.8.5.1"
+
/* controls for MSAD compatibility */
#define LDAP_CONTROL_X_DOMAIN_SCOPE "1.2.840.113556.1.4.1339"
#define LDAP_CONTROL_X_PERMISSIVE_MODIFY "1.2.840.113556.1.4.1413"
LDAPControl **sctrls,
LDAPControl **cctrls ));
+/*
+ * LDAP Password Policy controls
+ * in ppcontrol.c
+ */
+typedef enum passpolicyerror_enum {
+ PP_passwordExpired = 0,
+ PP_accountLocked = 1,
+ PP_changeAfterReset = 2,
+ PP_passwordModNotAllowed = 3,
+ PP_mustSupplyOldPassword = 4,
+ PP_invalidPasswordSyntax = 5,
+ PP_passwordTooShort = 6,
+ PP_passwordTooYoung = 7,
+ PP_passwordInHistory = 8,
+ PP_noError = 65535
+} LDAPPasswordPolicyError;
+
+LDAP_F( int )
+ldap_create_passwordpolicy_control LDAP_P((
+ LDAP *ld,
+ LDAPControl **ctrlp ));
+
+LDAP_F( int )
+ldap_parse_passwordpolicy_control LDAP_P((
+ LDAP *ld,
+ LDAPControl **ctrls,
+ int *expirep,
+ int *gracep,
+ LDAPPasswordPolicyError *errorp ));
LDAP_END_DECL
#endif /* _LDAP_H */
--- /dev/null
+/*
+ * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
+ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+ */
+/* Adapted for inclusion into OpenLDAP by Kurt D. Zeilenga */
+/*---
+ * Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
+ *
+ * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
+ * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
+ * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
+ * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
+ * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
+ * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
+ * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
+ * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
+ *---*/
+/* Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License
+ * can be found in the file "build/LICENSE-2.0.1" in this distribution
+ * of OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+
+#define PPOLICY_WARNING 0xa0L
+#define PPOLICY_ERROR 0xa1L
+
+#define PPOLICY_EXPIRE 0xa0L
+#define PPOLICY_GRACE 0xa1L
+
+/*---
+ ldap_create_passwordpolicy_control
+
+ Create and encode the Password Policy Request
+
+ ld (IN) An LDAP session handle, as obtained from a call to
+ ldap_init().
+
+ ctrlp (OUT) A result parameter that will be assigned the address
+ of an LDAPControl structure that contains the
+ passwordPolicyRequest control created by this function.
+ The memory occupied by the LDAPControl structure
+ SHOULD be freed when it is no longer in use by
+ calling ldap_control_free().
+
+
+ There is no control value for a password policy request
+ ---*/
+
+int
+ldap_create_passwordpolicy_control( LDAP *ld,
+ LDAPControl **ctrlp )
+{
+ BerElement *ber;
+
+ assert( ld != NULL );
+ assert( LDAP_VALID( ld ) );
+ assert( ctrlp != NULL );
+
+ if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return(LDAP_NO_MEMORY);
+ }
+
+ ld->ld_errno = ldap_create_control( LDAP_CONTROL_PASSWORDPOLICYREQUEST,
+ ber, 0, ctrlp);
+
+ ber_free(ber, 1);
+ return(ld->ld_errno);
+
+exit:
+ ber_free(ber, 1);
+ ld->ld_errno = LDAP_ENCODING_ERROR;
+ return(ld->ld_errno);
+}
+
+
+/*---
+ ldap_parse_passwordpolicy_control
+
+ Decode the passwordPolicyResponse control and return information.
+
+ ld (IN) An LDAP session handle.
+
+ ctrls (IN) The address of a NULL-terminated array of
+ LDAPControl structures, typically obtained
+ by a call to ldap_parse_result().
+
+ exptimep (OUT) This result parameter is filled in with the number of seconds before
+ the password will expire, if expiration is imminent
+ (imminency defined by the password policy). If expiration
+ is not imminent, the value is set to -1.
+
+ gracep (OUT) This result parameter is filled in with the number of grace logins after
+ the password has expired, before no further login attempts
+ will be allowed.
+
+ errorcodep (OUT) This result parameter is filled in with the error code of the password operation
+ If no error was detected, this error is set to PP_noError.
+
+ Ber encoding
+
+ PasswordPolicyResponseValue ::= SEQUENCE {
+ warning [0] CHOICE {
+ timeBeforeExpiration [0] INTEGER (0 .. maxInt),
+ graceLoginsRemaining [1] INTEGER (0 .. maxInt) } OPTIONAL
+ error [1] ENUMERATED {
+ passwordExpired (0),
+ accountLocked (1),
+ changeAfterReset (2),
+ passwordModNotAllowed (3),
+ mustSupplyOldPassword (4),
+ invalidPasswordSyntax (5),
+ passwordTooShort (6),
+ passwordTooYoung (7),
+ passwordInHistory (8) } OPTIONAL }
+
+---*/
+
+int
+ldap_parse_passwordpolicy_control(
+ LDAP *ld,
+ LDAPControl **ctrls,
+ int *expirep,
+ int *gracep,
+ LDAPPasswordPolicyError *errorp )
+{
+ BerElement *ber;
+ LDAPControl *pControl;
+ int i, exp = -1, grace = -1;
+ ber_tag_t tag;
+ ber_len_t berLen;
+ char *last;
+ LDAPPasswordPolicyError err = PP_noError;
+
+ assert( ld != NULL );
+ assert( LDAP_VALID( ld ) );
+
+ if (ctrls == NULL) {
+ ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
+ return(ld->ld_errno);
+ }
+
+ /* Search the list of control responses for a VLV control. */
+ for (i=0; ctrls[i]; i++) {
+ pControl = ctrls[i];
+ if (!strcmp(LDAP_CONTROL_PASSWORDPOLICYRESPONSE, pControl->ldctl_oid))
+ goto foundPPControl;
+ }
+
+ /* No sort control was found. */
+ ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
+ return(ld->ld_errno);
+
+foundPPControl:
+ /* Create a BerElement from the berval returned in the control. */
+ ber = ber_init(&pControl->ldctl_value);
+
+ if (ber == NULL) {
+ ld->ld_errno = LDAP_NO_MEMORY;
+ return(ld->ld_errno);
+ }
+
+ tag = ber_peek_tag( ber, &berLen );
+ if (tag != LBER_SEQUENCE) goto exit;
+
+ for( tag = ber_first_element( ber, &berLen, &last );
+ tag != LBER_DEFAULT;
+ tag = ber_next_element( ber, &berLen, last ) ) {
+ switch (tag) {
+ case PPOLICY_WARNING:
+ ber_skip_tag(ber, &berLen );
+ tag = ber_peek_tag( ber, &berLen );
+ switch( tag ) {
+ case PPOLICY_EXPIRE:
+ if (ber_get_int( ber, &exp ) == LBER_DEFAULT) goto exit;
+ break;
+ case PPOLICY_GRACE:
+ if (ber_get_int( ber, &grace ) == LBER_DEFAULT) goto exit;
+ break;
+ default:
+ goto exit;
+
+ }
+
+ break;
+ case PPOLICY_ERROR:
+ if (ber_get_enum( ber, (int *)&err ) == LBER_DEFAULT) goto exit;
+ break;
+ default:
+ goto exit;
+ }
+ }
+
+ ber_free(ber, 1);
+
+ /* Return data to the caller for items that were requested. */
+ if (expirep) *expirep = exp;
+ if (gracep) *gracep = grace;
+ if (errorp) *errorp = err;
+
+ ld->ld_errno = LDAP_SUCCESS;
+ return(ld->ld_errno);
+
+ exit:
+ ber_free(ber, 1);
+ ld->ld_errno = LDAP_DECODING_ERROR;
+ return(ld->ld_errno);
+}