From 3810fa18d87c2234b98e57a73898faab0bbe84e9 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Fri, 12 Mar 2004 21:22:32 +0000 Subject: [PATCH] Added PasswordPolicy control --- include/ldap.h | 34 +++++ libraries/libldap/Makefile.in | 7 +- libraries/libldap/ppcontrol.c | 216 ++++++++++++++++++++++++++++++++ libraries/libldap_r/Makefile.in | 6 +- 4 files changed, 259 insertions(+), 4 deletions(-) create mode 100644 libraries/libldap/ppcontrol.c diff --git a/include/ldap.h b/include/ldap.h index 0efd99e721..453931ac2a 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -238,6 +238,11 @@ typedef struct ldapcontrol { #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" @@ -1764,6 +1769,35 @@ ldap_passwd_s LDAP_P(( 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 */ diff --git a/libraries/libldap/Makefile.in b/libraries/libldap/Makefile.in index 5cbe6507de..dddebdada4 100644 --- a/libraries/libldap/Makefile.in +++ b/libraries/libldap/Makefile.in @@ -25,7 +25,9 @@ SRCS = bind.c open.c result.c error.c compare.c search.c \ getdn.c getentry.c getattr.c getvalues.c addentry.c \ request.c os-ip.c url.c sortctrl.c vlvctrl.c \ init.c options.c print.c string.c util-int.c schema.c \ - charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c + charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \ + pcontrol.c + OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \ controls.lo messages.lo references.lo extended.lo cyrus.lo \ modify.lo add.lo modrdn.lo delete.lo abandon.lo \ @@ -34,7 +36,8 @@ OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \ getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \ request.lo os-ip.lo url.lo sortctrl.lo vlvctrl.lo \ init.lo options.lo print.lo string.lo util-int.lo schema.lo \ - charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo + charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \ + ppcontrol.lo LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries diff --git a/libraries/libldap/ppcontrol.c b/libraries/libldap/ppcontrol.c new file mode 100644 index 0000000000..0cb62a0f25 --- /dev/null +++ b/libraries/libldap/ppcontrol.c @@ -0,0 +1,216 @@ +/* + * 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 +#include +#include +#include + +#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); +} diff --git a/libraries/libldap_r/Makefile.in b/libraries/libldap_r/Makefile.in index df4fbc18f5..688957da8a 100644 --- a/libraries/libldap_r/Makefile.in +++ b/libraries/libldap_r/Makefile.in @@ -27,7 +27,8 @@ XXSRCS = apitest.c test.c \ getdn.c getentry.c getattr.c getvalues.c addentry.c \ request.c os-ip.c url.c sortctrl.c vlvctrl.c \ init.c options.c print.c string.c util-int.c schema.c \ - charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c + charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \ + ppcontrol.c SRCS = threads.c rdwr.c tpool.c rq.c \ thr_posix.c thr_cthreads.c thr_thr.c thr_lwp.c thr_nt.c \ thr_pth.c thr_stub.c @@ -42,7 +43,8 @@ OBJS = threads.lo rdwr.lo tpool.lo rq.lo \ getdn.lo getentry.lo getattr.lo getvalues.lo addentry.lo \ request.lo os-ip.lo url.lo sortctrl.lo vlvctrl.lo \ init.lo options.lo print.lo string.lo util-int.lo schema.lo \ - charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo + charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \ + ppcontrol.lo LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries -- 2.39.5