1/*	$NetBSD: ppolicy.c,v 1.1.1.3 2010/12/12 15:21:34 adam Exp $	*/
2
3/* OpenLDAP: pkg/ldap/libraries/libldap/ppolicy.c,v 1.11.2.6 2010/04/13 20:22:59 kurt Exp */
4/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 2004-2010 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
62int
63ldap_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
120int
121ldap_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
193const char *
194ldap_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