1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 *
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
8 *
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
13 *
14 * The Original Code is Sun LDAP C SDK.
15 *
16 * The Initial Developer of the Original Code is Sun Microsystems, Inc.
17 *
18 * Portions created by Sun Microsystems, Inc are Copyright (C) 2005
19 * Sun Microsystems, Inc. All Rights Reserved.
20 *
21 * Contributor(s): abobrov@sun.com
22 *
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
34 *
35 * ***** END LICENSE BLOCK ***** */
36
37 #include "ldap-int.h"
38
39 /* ldap_create_passwordpolicy_control:
40
41 Parameters are
42
43 ld LDAP pointer to the desired connection
44
45 ctrlp the address of a place to put the constructed control
46 */
47
48 int
49 LDAP_CALL
ldap_create_passwordpolicy_control(LDAP * ld,LDAPControl ** ctrlp)50 ldap_create_passwordpolicy_control (
51 LDAP *ld,
52 LDAPControl **ctrlp
53 )
54 {
55 int rc;
56
57 if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
58 return( LDAP_PARAM_ERROR );
59 }
60
61 if ( ctrlp == NULL ) {
62 LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
63 return ( LDAP_PARAM_ERROR );
64 }
65
66 rc = nsldapi_build_control( LDAP_CONTROL_PASSWD_POLICY,
67 NULL, 0, 0, ctrlp );
68
69 LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
70 return( rc );
71 }
72
73 /* ldap_create_passwordpolicy_control_ext:
74
75 Parameters are
76
77 ld LDAP pointer to the desired connection
78
79 ctl_iscritical Indicates whether the control is critical of not. If
80 this field is non-zero, the operation will only be car-
81 ried out if the control is recognized by the server
82 and/or client
83
84 ctrlp the address of a place to put the constructed control
85 */
86
87 int
88 LDAP_CALL
ldap_create_passwordpolicy_control_ext(LDAP * ld,const char ctl_iscritical,LDAPControl ** ctrlp)89 ldap_create_passwordpolicy_control_ext (
90 LDAP *ld,
91 const char ctl_iscritical,
92 LDAPControl **ctrlp
93 )
94 {
95 int rc;
96
97 if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
98 return( LDAP_PARAM_ERROR );
99 }
100
101 if ( ctrlp == NULL ) {
102 LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
103 return ( LDAP_PARAM_ERROR );
104 }
105
106 rc = nsldapi_build_control( LDAP_CONTROL_PASSWD_POLICY,
107 NULL, 0, ctl_iscritical, ctrlp );
108
109 LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
110 return( rc );
111 }
112
113 /* ldap_parse_passwordpolicy_control:
114
115 Parameters are
116
117 ld LDAP pointer to the desired connection
118
119 ctrlp pointer to LDAPControl structure, obtained from
120 calling ldap_find_control() or by other means.
121
122 exptimep result parameter is filled in with the number of seconds before
123 the password will expire.
124
125 gracep result parameter is filled in with the number of grace logins
126 after the password has expired.
127
128 errorcodep result parameter is filled in with the error code of the
129 password operation.
130 */
131
132 int
133 LDAP_CALL
ldap_parse_passwordpolicy_control(LDAP * ld,LDAPControl * ctrlp,ber_int_t * expirep,ber_int_t * gracep,LDAPPasswordPolicyError * errorp)134 ldap_parse_passwordpolicy_control (
135 LDAP *ld,
136 LDAPControl *ctrlp,
137 ber_int_t *expirep,
138 ber_int_t *gracep,
139 LDAPPasswordPolicyError *errorp
140 )
141 {
142 ber_len_t len;
143 ber_tag_t tag;
144 ber_int_t pp_exp = -1;
145 ber_int_t pp_grace = -1;
146 ber_int_t pp_warning = -1;
147 ber_int_t pp_err = PP_noError;
148 BerElement *ber = NULL;
149
150 if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) ) {
151 return( LDAP_PARAM_ERROR );
152 }
153
154 if ( ctrlp == NULL ) {
155 LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL );
156 return ( LDAP_CONTROL_NOT_FOUND );
157 }
158
159 /* allocate a Ber element with the contents of the control's struct berval */
160 if ( ( ber = ber_init( &ctrlp->ldctl_value ) ) == NULL ) {
161 LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
162 return( LDAP_NO_MEMORY );
163 }
164
165 /*
166 * The control value should look like this:
167 *
168 * PasswordPolicyResponseValue ::= SEQUENCE {
169 * warning [0] CHOICE {
170 * timeBeforeExpiration [0] INTEGER (0 .. maxInt),
171 * graceLoginsRemaining [1] INTEGER (0 .. maxInt) } OPTIONAL
172 * error [1] ENUMERATED {
173 * passwordExpired (0),
174 * accountLocked (1),
175 * changeAfterReset (2),
176 * passwordModNotAllowed (3),
177 * mustSupplyOldPassword (4),
178 * insufficientPasswordQuality (5),
179 * passwordTooShort (6),
180 * passwordTooYoung (7),
181 * passwordInHistory (8) } OPTIONAL }
182 */
183
184 if ( ber_scanf( ber, "{" ) == LBER_ERROR ) {
185 LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL );
186 ber_free( ber, 1 );
187 return( LDAP_DECODING_ERROR );
188 }
189
190 tag = ber_peek_tag( ber, &len );
191
192 while ( (tag != LBER_ERROR) && (tag != LBER_END_OF_SEQORSET) ) {
193 if ( tag == ( LBER_CONSTRUCTED | LBER_CLASS_CONTEXT ) ) {
194 ber_skip_tag( ber, &len );
195 if ( ber_scanf( ber, "ti", &tag, &pp_warning ) == LBER_ERROR ) {
196 LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL );
197 ber_free( ber, 1 );
198 return( LDAP_DECODING_ERROR );
199 }
200 if ( tag == LBER_CLASS_CONTEXT ) {
201 pp_exp = pp_warning;
202 } else if ( tag == ( LBER_CLASS_CONTEXT | 0x01 ) ) {
203 pp_grace = pp_warning;
204 }
205 } else if ( tag == ( LBER_CLASS_CONTEXT | 0x01 ) ) {
206 if ( ber_scanf( ber, "ti", &tag, &pp_err ) == LBER_ERROR ) {
207 LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL );
208 ber_free( ber, 1 );
209 return( LDAP_DECODING_ERROR );
210 }
211 }
212 if ( tag == LBER_DEFAULT ) {
213 LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL );
214 ber_free( ber, 1 );
215 return( LDAP_DECODING_ERROR );
216 }
217 tag = ber_skip_tag( ber, &len );
218 }
219
220 if (expirep) *expirep = pp_exp;
221 if (gracep) *gracep = pp_grace;
222 if (errorp) *errorp = pp_err;
223
224 /* the ber encoding is no longer needed */
225 ber_free( ber, 1 );
226 return( LDAP_SUCCESS );
227 }
228
229 /* ldap_parse_passwordpolicy_control_ext:
230
231 Parameters are
232
233 ld LDAP pointer to the desired connection
234
235 ctrlp An array of controls obtained from calling
236 ldap_parse_result on the set of results
237 returned by the server
238
239 exptimep result parameter is filled in with the number of seconds before
240 the password will expire.
241
242 gracep result parameter is filled in with the number of grace logins
243 after the password has expired.
244
245 errorcodep result parameter is filled in with the error code of the
246 password operation.
247 */
248
249 int
250 LDAP_CALL
ldap_parse_passwordpolicy_control_ext(LDAP * ld,LDAPControl ** ctrlp,ber_int_t * expirep,ber_int_t * gracep,LDAPPasswordPolicyError * errorp)251 ldap_parse_passwordpolicy_control_ext (
252 LDAP *ld,
253 LDAPControl **ctrlp,
254 ber_int_t *expirep,
255 ber_int_t *gracep,
256 LDAPPasswordPolicyError *errorp
257 )
258 {
259 int i, foundPPControl;
260 LDAPControl *PPCtrlp = NULL;
261
262 if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) ) {
263 return( LDAP_PARAM_ERROR );
264 }
265
266 /* find the control in the list of controls if it exists */
267 if ( ctrlp == NULL ) {
268 LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL );
269 return ( LDAP_CONTROL_NOT_FOUND );
270 }
271 foundPPControl = 0;
272 for ( i = 0; (( ctrlp[i] != NULL ) && ( !foundPPControl )); i++ ) {
273 foundPPControl = !strcmp( ctrlp[i]->ldctl_oid, LDAP_CONTROL_PASSWD_POLICY );
274 }
275 if ( !foundPPControl ) {
276 LDAP_SET_LDERRNO( ld, LDAP_CONTROL_NOT_FOUND, NULL, NULL );
277 return ( LDAP_CONTROL_NOT_FOUND );
278 } else {
279 /* let local var point to the control */
280 PPCtrlp = ctrlp[i-1];
281 }
282
283 return (
284 ldap_parse_passwordpolicy_control( ld, PPCtrlp, expirep, gracep, errorp ));
285 }
286
287 const char *
288 LDAP_CALL
ldap_passwordpolicy_err2txt(LDAPPasswordPolicyError err)289 ldap_passwordpolicy_err2txt( LDAPPasswordPolicyError err )
290 {
291 switch(err) {
292 case PP_passwordExpired:
293 return "Password expired";
294 case PP_accountLocked:
295 return "Account locked";
296 case PP_changeAfterReset:
297 return "Password must be changed";
298 case PP_passwordModNotAllowed:
299 return "Policy prevents password modification";
300 case PP_mustSupplyOldPassword:
301 return "Policy requires old password in order to change password";
302 case PP_insufficientPasswordQuality:
303 return "Password fails quality checks";
304 case PP_passwordTooShort:
305 return "Password is too short for policy";
306 case PP_passwordTooYoung:
307 return "Password has been changed too recently";
308 case PP_passwordInHistory:
309 return "New password is in list of old passwords";
310 case PP_noError:
311 return "No error";
312 default:
313 return "Unknown error code";
314 }
315 }
316