xref: /netbsd-src/external/bsd/openldap/dist/libraries/libldap/ppolicy.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: ppolicy.c,v 1.1.1.4 2014/05/28 09:58:41 tron Exp $	*/
2 
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 2004-2014 The OpenLDAP Foundation.
7  * Portions Copyright 2004 Hewlett-Packard Company.
8  * Portions Copyright 2004 Howard Chu, Symas Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted only as authorized by the OpenLDAP
13  * Public License.
14  *
15  * A copy of this license is available in the file LICENSE in the
16  * top-level directory of the distribution or, alternatively, at
17  * <http://www.OpenLDAP.org/license.html>.
18  */
19 /* ACKNOWLEDGEMENTS:
20  * This work was developed by Howard Chu for inclusion in
21  * OpenLDAP Software, based on prior work by Neil Dunbar (HP).
22  * This work was sponsored by the Hewlett-Packard Company.
23  */
24 
25 #include "portable.h"
26 
27 #include <stdio.h>
28 #include <ac/stdlib.h>
29 #include <ac/string.h>
30 #include <ac/time.h>
31 
32 #include "ldap-int.h"
33 
34 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
35 
36 /* IMPLICIT TAGS, all context-specific */
37 #define PPOLICY_WARNING 0xa0L	/* constructed + 0 */
38 #define PPOLICY_ERROR 0x81L		/* primitive + 1 */
39 
40 #define PPOLICY_EXPIRE 0x80L	/* primitive + 0 */
41 #define PPOLICY_GRACE  0x81L	/* primitive + 1 */
42 
43 /*---
44    ldap_create_passwordpolicy_control
45 
46    Create and encode the Password Policy Request
47 
48    ld        (IN)  An LDAP session handle, as obtained from a call to
49 				   ldap_init().
50 
51    ctrlp     (OUT) A result parameter that will be assigned the address
52 				   of an LDAPControl structure that contains the
53 				   passwordPolicyRequest control created by this function.
54 				   The memory occupied by the LDAPControl structure
55 				   SHOULD be freed when it is no longer in use by
56 				   calling ldap_control_free().
57 
58 
59    There is no control value for a password policy request
60  ---*/
61 
62 int
63 ldap_create_passwordpolicy_control( LDAP *ld,
64                                     LDAPControl **ctrlp )
65 {
66 	assert( ld != NULL );
67 	assert( LDAP_VALID( ld ) );
68 	assert( ctrlp != NULL );
69 
70 	ld->ld_errno = ldap_control_create( LDAP_CONTROL_PASSWORDPOLICYREQUEST,
71 		0, NULL, 0, ctrlp );
72 
73 	return ld->ld_errno;
74 }
75 
76 
77 /*---
78    ldap_parse_passwordpolicy_control
79 
80    Decode the passwordPolicyResponse control and return information.
81 
82    ld           (IN)   An LDAP session handle.
83 
84    ctrl         (IN)   The address of an
85 					   LDAPControl structure, either obtained
86 					   by running thorugh the list of response controls or
87 					   by a call to ldap_control_find().
88 
89    exptimep     (OUT)  This result parameter is filled in with the number of seconds before
90                                            the password will expire, if expiration is imminent
91                                            (imminency defined by the password policy). If expiration
92                                            is not imminent, the value is set to -1.
93 
94    gracep       (OUT)  This result parameter is filled in with the number of grace logins after
95                                            the password has expired, before no further login attempts
96                                            will be allowed.
97 
98    errorcodep   (OUT)  This result parameter is filled in with the error code of the password operation
99                                            If no error was detected, this error is set to PP_noError.
100 
101    Ber encoding
102 
103    PasswordPolicyResponseValue ::= SEQUENCE {
104        warning [0] CHOICE {
105            timeBeforeExpiration [0] INTEGER (0 .. maxInt),
106            graceLoginsRemaining [1] INTEGER (0 .. maxInt) } OPTIONAL
107        error [1] ENUMERATED {
108            passwordExpired        (0),
109            accountLocked          (1),
110            changeAfterReset       (2),
111            passwordModNotAllowed  (3),
112            mustSupplyOldPassword  (4),
113            invalidPasswordSyntax  (5),
114            passwordTooShort       (6),
115            passwordTooYoung       (7),
116            passwordInHistory      (8) } OPTIONAL }
117 
118 ---*/
119 
120 int
121 ldap_parse_passwordpolicy_control(
122 	LDAP           *ld,
123 	LDAPControl    *ctrl,
124 	ber_int_t      *expirep,
125 	ber_int_t      *gracep,
126 	LDAPPasswordPolicyError *errorp )
127 {
128 	BerElement  *ber;
129 	int exp = -1, grace = -1;
130 	ber_tag_t tag;
131 	ber_len_t berLen;
132         char *last;
133 	int err = PP_noError;
134 
135 	assert( ld != NULL );
136 	assert( LDAP_VALID( ld ) );
137 	assert( ctrl != NULL );
138 
139 	if ( !ctrl->ldctl_value.bv_val ) {
140 		ld->ld_errno = LDAP_DECODING_ERROR;
141 		return(ld->ld_errno);
142 	}
143 
144 	/* Create a BerElement from the berval returned in the control. */
145 	ber = ber_init(&ctrl->ldctl_value);
146 
147 	if (ber == NULL) {
148 		ld->ld_errno = LDAP_NO_MEMORY;
149 		return(ld->ld_errno);
150 	}
151 
152 	tag = ber_peek_tag( ber, &berLen );
153 	if (tag != LBER_SEQUENCE) goto exit;
154 
155 	for( tag = ber_first_element( ber, &berLen, &last );
156 		tag != LBER_DEFAULT;
157 		tag = ber_next_element( ber, &berLen, last ) )
158 	{
159 		switch (tag) {
160 		case PPOLICY_WARNING:
161 			ber_skip_tag(ber, &berLen );
162 			tag = ber_peek_tag( ber, &berLen );
163 			switch( tag ) {
164 			case PPOLICY_EXPIRE:
165 				if (ber_get_int( ber, &exp ) == LBER_DEFAULT) goto exit;
166 				break;
167 			case PPOLICY_GRACE:
168 				if (ber_get_int( ber, &grace ) == LBER_DEFAULT) goto exit;
169 				break;
170 			default:
171 				goto exit;
172 			}
173 			break;
174 		case PPOLICY_ERROR:
175 			if (ber_get_enum( ber, &err ) == LBER_DEFAULT) goto exit;
176 			break;
177 		default:
178 			goto exit;
179 		}
180 	}
181 
182 	ber_free(ber, 1);
183 
184 	/* Return data to the caller for items that were requested. */
185 	if (expirep) *expirep = exp;
186 	if (gracep) *gracep = grace;
187 	if (errorp) *errorp = err;
188 
189 	ld->ld_errno = LDAP_SUCCESS;
190 	return(ld->ld_errno);
191 
192   exit:
193 	ber_free(ber, 1);
194 	ld->ld_errno = LDAP_DECODING_ERROR;
195 	return(ld->ld_errno);
196 }
197 
198 const char *
199 ldap_passwordpolicy_err2txt( LDAPPasswordPolicyError err )
200 {
201 	switch(err) {
202 	case PP_passwordExpired: return "Password expired";
203 	case PP_accountLocked: return "Account locked";
204 	case PP_changeAfterReset: return "Password must be changed";
205 	case PP_passwordModNotAllowed: return "Policy prevents password modification";
206 	case PP_mustSupplyOldPassword: return "Policy requires old password in order to change password";
207 	case PP_insufficientPasswordQuality: return "Password fails quality checks";
208 	case PP_passwordTooShort: return "Password is too short for policy";
209 	case PP_passwordTooYoung: return "Password has been changed too recently";
210 	case PP_passwordInHistory: return "New password is in list of old passwords";
211 	case PP_noError: return "No error";
212 	default: return "Unknown error code";
213 	}
214 }
215 
216 #endif /* LDAP_CONTROL_PASSWORDPOLICYREQUEST */
217