xref: /netbsd-src/external/bsd/openldap/dist/libraries/libldap/ppolicy.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: ppolicy.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $	*/
2 
3 /* OpenLDAP: pkg/ldap/libraries/libldap/ppolicy.c,v 1.11.2.5 2009/01/22 00:00:55 kurt Exp */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 2004-2009 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 	/* Create a BerElement from the berval returned in the control. */
140 	ber = ber_init(&ctrl->ldctl_value);
141 
142 	if (ber == NULL) {
143 		ld->ld_errno = LDAP_NO_MEMORY;
144 		return(ld->ld_errno);
145 	}
146 
147 	tag = ber_peek_tag( ber, &berLen );
148 	if (tag != LBER_SEQUENCE) goto exit;
149 
150 	for( tag = ber_first_element( ber, &berLen, &last );
151 		tag != LBER_DEFAULT;
152 		tag = ber_next_element( ber, &berLen, last ) )
153 	{
154 		switch (tag) {
155 		case PPOLICY_WARNING:
156 			ber_skip_tag(ber, &berLen );
157 			tag = ber_peek_tag( ber, &berLen );
158 			switch( tag ) {
159 			case PPOLICY_EXPIRE:
160 				if (ber_get_int( ber, &exp ) == LBER_DEFAULT) goto exit;
161 				break;
162 			case PPOLICY_GRACE:
163 				if (ber_get_int( ber, &grace ) == LBER_DEFAULT) goto exit;
164 				break;
165 			default:
166 				goto exit;
167 			}
168 			break;
169 		case PPOLICY_ERROR:
170 			if (ber_get_enum( ber, &err ) == LBER_DEFAULT) goto exit;
171 			break;
172 		default:
173 			goto exit;
174 		}
175 	}
176 
177 	ber_free(ber, 1);
178 
179 	/* Return data to the caller for items that were requested. */
180 	if (expirep) *expirep = exp;
181 	if (gracep) *gracep = grace;
182 	if (errorp) *errorp = err;
183 
184 	ld->ld_errno = LDAP_SUCCESS;
185 	return(ld->ld_errno);
186 
187   exit:
188 	ber_free(ber, 1);
189 	ld->ld_errno = LDAP_DECODING_ERROR;
190 	return(ld->ld_errno);
191 }
192 
193 const char *
194 ldap_passwordpolicy_err2txt( LDAPPasswordPolicyError err )
195 {
196 	switch(err) {
197 	case PP_passwordExpired: return "Password expired";
198 	case PP_accountLocked: return "Account locked";
199 	case PP_changeAfterReset: return "Password must be changed";
200 	case PP_passwordModNotAllowed: return "Policy prevents password modification";
201 	case PP_mustSupplyOldPassword: return "Policy requires old password in order to change password";
202 	case PP_insufficientPasswordQuality: return "Password fails quality checks";
203 	case PP_passwordTooShort: return "Password is too short for policy";
204 	case PP_passwordTooYoung: return "Password has been changed too recently";
205 	case PP_passwordInHistory: return "New password is in list of old passwords";
206 	case PP_noError: return "No error";
207 	default: return "Unknown error code";
208 	}
209 }
210 
211 #endif /* LDAP_CONTROL_PASSWORDPOLICYREQUEST */
212