]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/passwd.c
d801fb926082891fffb37868102fd109796be6c6
[openldap] / servers / slapd / back-bdb / passwd.c
1 /* passwd.c - bdb backend password routines */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7
8 #include "portable.h"
9
10 #include <stdio.h>
11 #include <ac/string.h>
12
13 #include "back-bdb.h"
14 #include "external.h"
15
16 int
17 bdb_exop_passwd(
18         Backend         *be,
19         Connection              *conn,
20         Operation               *op,
21         const char              *reqoid,
22         struct berval   *reqdata,
23         char                    **rspoid,
24         struct berval   **rspdata,
25         LDAPControl             *** rspctrls,
26         const char              **text,
27         BerVarray *refs )
28 {
29         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
30         int rc;
31         Entry *e = NULL;
32         struct berval hash = { 0, NULL };
33         DB_TXN *ltid = NULL;
34         struct bdb_op_info opinfo;
35         char textbuf[SLAP_TEXT_BUFLEN];
36         size_t textlen = sizeof textbuf;
37
38         struct berval id = { 0, NULL };
39         struct berval new = { 0, NULL };
40
41         struct berval dn;
42         struct berval ndn;
43
44         u_int32_t       locker = 0;
45         DB_LOCK         lock;
46
47         assert( reqoid != NULL );
48         assert( strcmp( LDAP_EXOP_MODIFY_PASSWD, reqoid ) == 0 );
49
50         rc = slap_passwd_parse( reqdata,
51                 &id, NULL, &new, text );
52
53 #ifdef NEW_LOGGING
54         LDAP_LOG ( ACL, ENTRY, 
55                 "==>bdb_exop_passwd: \"%s\"\n", id.bv_val ? id.bv_val : "", 0, 0  );
56 #else
57         Debug( LDAP_DEBUG_ARGS, "==> bdb_exop_passwd: \"%s\"\n",
58                 id.bv_val ? id.bv_val : "", 0, 0 );
59 #endif
60
61         if( rc != LDAP_SUCCESS ) {
62                 goto done;
63         }
64
65         if( new.bv_len == 0 ) {
66                 slap_passwd_generate(&new);
67
68                 if( new.bv_len == 0 ) {
69                         *text = "password generation failed.";
70                         rc = LDAP_OTHER;
71                         goto done;
72                 }
73                 
74                 *rspdata = slap_passwd_return( &new );
75         }
76
77         slap_passwd_hash( &new, &hash );
78
79         if( hash.bv_len == 0 ) {
80                 *text = "password hash failed";
81                 rc = LDAP_OTHER;
82                 goto done;
83         }
84
85         if( id.bv_len ) {
86                 dn = id;
87         } else {
88                 dn = op->o_dn;
89         }
90
91 #ifdef NEW_LOGGING
92         LDAP_LOG ( ACL, DETAIL1, "bdb_exop_passwd: \"%s\"%s\"\n",
93                 dn.bv_val, id.bv_len ? " (proxy)" : "", 0 );
94 #else
95         Debug( LDAP_DEBUG_TRACE, "bdb_exop_passwd: \"%s\"%s\n",
96                 dn.bv_val, id.bv_len ? " (proxy)" : "", 0 );
97 #endif
98
99         if( dn.bv_len == 0 ) {
100                 *text = "No password is associated with the Root DSE";
101                 rc = LDAP_UNWILLING_TO_PERFORM;
102                 goto done;
103         }
104
105         rc = dnNormalize2( NULL, &dn, &ndn );
106         if( rc != LDAP_SUCCESS ) {
107                 *text = "Invalid DN";
108                 goto done;
109         }
110
111         if( 0 ) {
112 retry:  /* transaction retry */
113                 if ( e != NULL ) {
114                         bdb_cache_delete_entry(&bdb->bi_cache, e);
115                         bdb_unlocked_cache_return_entry_w(&bdb->bi_cache, e);
116                 }
117 #ifdef NEW_LOGGING
118                 LDAP_LOG ( ACL, DETAIL1, "bdb_exop_passwd: retrying...\n", 0, 0, 0 );
119 #else
120                 Debug( LDAP_DEBUG_TRACE, "bdb_exop_passwd: retrying...\n", 0, 0, 0 );
121 #endif
122                 rc = TXN_ABORT( ltid );
123                 ltid = NULL;
124                 op->o_private = NULL;
125                 if( rc != 0 ) {
126                         rc = LDAP_OTHER;
127                         *text = "internal error";
128                         goto done;
129                 }
130                 ldap_pvt_thread_yield();
131         }
132
133         /* begin transaction */
134         rc = TXN_BEGIN( bdb->bi_dbenv, NULL, &ltid, 
135                 bdb->bi_db_opflags );
136         *text = NULL;
137         if( rc != 0 ) {
138 #ifdef NEW_LOGGING
139                 LDAP_LOG ( ACL, ERR, 
140                         "bdb_exop_passwd: txn_begin failed: %s (%d)\n", 
141                         db_strerror(rc), rc, 0 );
142 #else
143                 Debug( LDAP_DEBUG_TRACE,
144                         "bdb_exop_passwd: txn_begin failed: %s (%d)\n",
145                         db_strerror(rc), rc, 0 );
146 #endif
147                 rc = LDAP_OTHER;
148                 *text = "internal error";
149                 goto done;
150         }
151
152         locker = TXN_ID ( ltid );
153
154         opinfo.boi_bdb = be;
155         opinfo.boi_txn = ltid;
156         opinfo.boi_locker = locker;
157         opinfo.boi_err = 0;
158         op->o_private = &opinfo;
159
160         /* get entry */
161         rc = bdb_dn2entry_w( be, ltid, &ndn, &e, NULL, 0 , locker, &lock);
162
163         switch(rc) {
164         case DB_LOCK_DEADLOCK:
165         case DB_LOCK_NOTGRANTED:
166                 goto retry;
167         case DB_NOTFOUND:
168         case 0:
169                 break;
170         case LDAP_BUSY:
171                 *text = "ldap server busy";
172                 goto done;
173         default:
174                 rc = LDAP_OTHER;
175                 *text = "internal error";
176                 goto done;
177         }
178
179         if( e == NULL ) {
180                 *text = "could not locate authorization entry";
181                 rc = LDAP_NO_SUCH_OBJECT;
182                 goto done;
183         }
184
185 #ifdef BDB_SUBENTRIES
186         if( is_entry_subentry( e ) ) {
187                 /* entry is an alias, don't allow operation */
188                 *text = "authorization entry is subentry";
189                 rc = LDAP_OTHER;
190                 goto done;
191         }
192 #endif
193 #ifdef BDB_ALIASES
194         if( is_entry_alias( e ) ) {
195                 /* entry is an alias, don't allow operation */
196                 *text = "authorization entry is alias";
197                 rc = LDAP_ALIAS_PROBLEM;
198                 goto done;
199         }
200 #endif
201
202         if( is_entry_referral( e ) ) {
203                 /* entry is an referral, don't allow operation */
204                 *text = "authorization entry is referral";
205                 rc = LDAP_OTHER;
206                 goto done;
207         }
208
209         {
210                 Modifications ml;
211                 struct berval vals[2];
212
213                 vals[0] = hash;
214                 vals[1].bv_val = NULL;
215
216                 ml.sml_desc = slap_schema.si_ad_userPassword;
217                 ml.sml_bvalues = vals;
218                 ml.sml_op = LDAP_MOD_REPLACE;
219                 ml.sml_next = NULL;
220
221                 rc = bdb_modify_internal( be, conn, op, ltid,
222                         &ml, e, text, textbuf, textlen );
223
224                 switch(rc) {
225                 case DB_LOCK_DEADLOCK:
226                 case DB_LOCK_NOTGRANTED:
227                         *text = NULL;
228                         goto retry;
229                 case 0:
230                         *text = NULL;
231                         break;
232                 default:
233                         rc = LDAP_OTHER;
234                         *text = "entry modify failed";
235                         goto done;
236                 }
237
238                 /* change the entry itself */
239                 rc = bdb_id2entry_update( be, ltid, e );
240                 if( rc != 0 ) {
241                         switch(rc) {
242                         case DB_LOCK_DEADLOCK:
243                         case DB_LOCK_NOTGRANTED:
244                                 goto retry;
245                         }
246                         *text = "entry update failed";
247                         rc = LDAP_OTHER;
248                 }
249
250                 if( rc == 0 ) {
251                         if( op->o_noop ) {
252                                 rc = TXN_ABORT( ltid );
253                         } else {
254                                 rc = TXN_COMMIT( ltid, 0 );
255                         }
256                         ltid = NULL;
257                 }
258                 op->o_private = NULL;
259
260                 if( rc == LDAP_SUCCESS ) {
261                         replog( be, op, &e->e_name, &e->e_nname, &ml );
262                 }
263         }
264
265 done:
266         if( e != NULL ) {
267                 bdb_unlocked_cache_return_entry_w( &bdb->bi_cache, e );
268         }
269                 
270         if( hash.bv_val != NULL ) {
271                 free( hash.bv_val );
272         }
273
274         if( ltid != NULL ) {
275                 TXN_ABORT( ltid );
276                 op->o_private = NULL;
277         }
278
279         return rc;
280 }