]> git.sur5r.net Git - openldap/blob - libraries/libldap/ppolicy.c
16193f64008c5c830f4582712108859a85d3f147
[openldap] / libraries / libldap / ppolicy.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2004-2007 The OpenLDAP Foundation.
5  * Portions Copyright 2004 Hewlett-Packard Company.
6  * Portions Copyright 2004 Howard Chu, Symas Corp.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 /* ACKNOWLEDGEMENTS:
18  * This work was developed by Howard Chu for inclusion in
19  * OpenLDAP Software, based on prior work by Neil Dunbar (HP).
20  * This work was sponsored by the Hewlett-Packard Company.
21  */
22
23 #include "portable.h"
24
25 #include <stdio.h>
26 #include <ac/stdlib.h>
27 #include <ac/string.h>
28 #include <ac/time.h>
29
30 #include "ldap-int.h"
31
32 #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
33
34 /* IMPLICIT TAGS, all context-specific */
35 #define PPOLICY_WARNING 0xa0L   /* constructed + 0 */
36 #define PPOLICY_ERROR 0x81L             /* primitive + 1 */
37
38 #define PPOLICY_EXPIRE 0x80L    /* primitive + 0 */
39 #define PPOLICY_GRACE  0x81L    /* primitive + 1 */
40
41 /*---
42    ldap_create_passwordpolicy_control
43    
44    Create and encode the Password Policy Request
45
46    ld        (IN)  An LDAP session handle, as obtained from a call to
47                                    ldap_init().
48    
49    ctrlp     (OUT) A result parameter that will be assigned the address
50                                    of an LDAPControl structure that contains the 
51                                    passwordPolicyRequest control created by this function.
52                                    The memory occupied by the LDAPControl structure
53                                    SHOULD be freed when it is no longer in use by
54                                    calling ldap_control_free().
55                                           
56    
57    There is no control value for a password policy request
58  ---*/
59
60 int
61 ldap_create_passwordpolicy_control( LDAP *ld,
62                                     LDAPControl **ctrlp )
63 {
64         BerElement *ber;
65
66         assert( ld != NULL );
67         assert( LDAP_VALID( ld ) );
68         assert( ctrlp != NULL );
69
70         if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
71                 ld->ld_errno = LDAP_NO_MEMORY;
72                 return(LDAP_NO_MEMORY);
73         }
74
75         ld->ld_errno = ldap_create_control( LDAP_CONTROL_PASSWORDPOLICYREQUEST,
76                 ber, 0, ctrlp);
77
78         ber_free(ber, 1);
79         return(ld->ld_errno);
80 }
81
82
83 /*---
84    ldap_parse_passwordpolicy_control
85    
86    Decode the passwordPolicyResponse control and return information.
87
88    ld           (IN)   An LDAP session handle.
89    
90    ctrl         (IN)   The address of an
91                                            LDAPControl structure, typically obtained 
92                                            by a call to ldap_find_control().
93
94    exptimep     (OUT)  This result parameter is filled in with the number of seconds before
95                                            the password will expire, if expiration is imminent
96                                            (imminency defined by the password policy). If expiration
97                                            is not imminent, the value is set to -1.
98
99    gracep       (OUT)  This result parameter is filled in with the number of grace logins after
100                                            the password has expired, before no further login attempts
101                                            will be allowed.
102
103    errorcodep   (OUT)  This result parameter is filled in with the error code of the password operation
104                                            If no error was detected, this error is set to PP_noError.
105    
106    Ber encoding
107    
108    PasswordPolicyResponseValue ::= SEQUENCE {
109        warning [0] CHOICE {
110            timeBeforeExpiration [0] INTEGER (0 .. maxInt),
111            graceLoginsRemaining [1] INTEGER (0 .. maxInt) } OPTIONAL
112        error [1] ENUMERATED {
113            passwordExpired        (0),
114            accountLocked          (1),
115            changeAfterReset       (2),
116            passwordModNotAllowed  (3),
117            mustSupplyOldPassword  (4),
118            invalidPasswordSyntax  (5),
119            passwordTooShort       (6),
120            passwordTooYoung       (7),
121            passwordInHistory      (8) } OPTIONAL }
122            
123 ---*/
124
125 int
126 ldap_parse_passwordpolicy_control(
127         LDAP           *ld,
128         LDAPControl    *ctrl,
129         ber_int_t      *expirep,
130         ber_int_t      *gracep,
131         LDAPPasswordPolicyError *errorp )
132 {
133         BerElement  *ber;
134         int exp = -1, grace = -1;
135         ber_tag_t tag;
136         ber_len_t berLen;
137         char *last;
138         int err = PP_noError;
139         
140         assert( ld != NULL );
141         assert( LDAP_VALID( ld ) );
142         assert( ctrl != NULL );
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 */