]> git.sur5r.net Git - openldap/blob - servers/slapd/back-bdb/passwd.c
Mostly working modify
[openldap] / servers / slapd / back-bdb / passwd.c
1 /* passwd.c - bdb backend password routines */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2000 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         struct berval   *** refs )
28 {
29         struct bdb_info *bdb = (struct bdb_info *) be->be_private;
30         int rc;
31         Entry *e = NULL;
32         struct berval *hash = NULL;
33         DB_TXN *ltid = NULL;
34         struct bdb_op_info opinfo;
35
36         struct berval *id = NULL;
37         struct berval *new = NULL;
38
39         char *dn;
40
41         assert( reqoid != NULL );
42         assert( strcmp( LDAP_EXOP_X_MODIFY_PASSWD, reqoid ) == 0 );
43
44         rc = slap_passwd_parse( reqdata,
45                 &id, NULL, &new, text );
46
47         Debug( LDAP_DEBUG_ARGS, "==> bdb_exop_passwd: \"%s\"\n",
48                 id ? id->bv_val : "", 0, 0 );
49
50         if( rc != LDAP_SUCCESS ) {
51                 goto done;
52         }
53
54         if( new == NULL || new->bv_len == 0 ) {
55                 new = slap_passwd_generate();
56
57                 if( new == NULL || new->bv_len == 0 ) {
58                         *text = "password generation failed.";
59                         rc = LDAP_OTHER;
60                         goto done;
61                 }
62                 
63                 *rspdata = slap_passwd_return( new );
64         }
65
66         hash = slap_passwd_hash( new );
67
68         if( hash == NULL || hash->bv_len == 0 ) {
69                 *text = "password hash failed";
70                 rc = LDAP_OTHER;
71                 goto done;
72         }
73
74         dn = id ? id->bv_val : op->o_dn;
75
76         Debug( LDAP_DEBUG_TRACE, "passwd: \"%s\"%s\n",
77                 dn, id ? " (proxy)" : "", 0 );
78
79         if( dn == NULL || dn[0] == '\0' ) {
80                 *text = "No password is associated with the Root DSE";
81                 rc = LDAP_OPERATIONS_ERROR;
82                 goto done;
83         }
84
85         if (0) {
86                 /* transaction retry */
87 retry:  rc = txn_abort( ltid );
88                 ltid = NULL;
89                 op->o_private = NULL;
90                 if( rc != 0 ) {
91                         rc = LDAP_OTHER;
92                         *text = "internal error";
93                         goto done;
94                 }
95         }
96
97         /* begin transaction */
98         rc = txn_begin( bdb->bi_dbenv, NULL, &ltid, 0 );
99         if( rc != 0 ) {
100                 Debug( LDAP_DEBUG_TRACE,
101                         "bdb_exop_passwd: txn_begin failed: %s (%d)\n",
102                         db_strerror(rc), rc, 0 );
103                 rc = LDAP_OTHER;
104                 *text = "internal error";
105                 goto done;
106         }
107
108         opinfo.boi_bdb = be;
109         opinfo.boi_txn = ltid;
110         opinfo.boi_err = 0;
111         op->o_private = &opinfo;
112
113         /* get entry */
114         rc = bdb_dn2entry( be, ltid, dn, &e, NULL, 0 );
115
116         switch(rc) {
117         case DB_LOCK_DEADLOCK:
118         case DB_LOCK_NOTGRANTED:
119                 goto retry;
120         case DB_NOTFOUND:
121         case 0:
122                 break;
123         default:
124                 rc = LDAP_OTHER;
125                 *text = "internal error";
126                 goto done;
127         }
128
129         if( e == NULL ) {
130                 *text = "could not locate authorization entry";
131                 rc = LDAP_OPERATIONS_ERROR;
132                 goto done;
133         }
134
135         if( is_entry_alias( e ) ) {
136                 /* entry is an alias, don't allow operation */
137                 *text = "authorization entry is alias";
138                 rc = LDAP_ALIAS_PROBLEM;
139                 goto done;
140         }
141
142
143         if( is_entry_referral( e ) ) {
144                 /* entry is an referral, don't allow operation */
145                 *text = "authorization entry is referral";
146                 rc = LDAP_OPERATIONS_ERROR;
147                 goto done;
148         }
149
150         {
151                 Modifications ml;
152                 struct berval *vals[2];
153
154                 vals[0] = hash;
155                 vals[1] = NULL;
156
157                 ml.sml_desc = slap_schema.si_ad_userPassword;
158                 ml.sml_bvalues = vals;
159                 ml.sml_op = LDAP_MOD_REPLACE;
160                 ml.sml_next = NULL;
161
162                 rc = bdb_modify_internal( be, conn, op, ltid,
163                         &ml, e, text );
164
165                 switch(rc) {
166                 case DB_LOCK_DEADLOCK:
167                 case DB_LOCK_NOTGRANTED:
168                         bdb_entry_return( be, e );
169                         e = NULL;
170                         goto retry;
171                 case 0:
172                         break;
173                 default:
174                         rc = LDAP_OTHER;
175                         *text = "entry modify failed";
176                         goto done;
177                 }
178
179         }
180
181         /* change the entry itself */
182         rc = bdb_id2entry_update( be, ltid, e );
183         if( rc != 0 ) {
184                 switch(rc) {
185                 case DB_LOCK_DEADLOCK:
186                 case DB_LOCK_NOTGRANTED:
187                         bdb_entry_return( be, e );
188                         goto retry;
189                 }
190                 *text = "entry update failed";
191                 rc = LDAP_OTHER;
192                 goto done;
193         }
194
195 done:
196         if( e != NULL ) {
197                 bdb_entry_return( be, e );
198         }
199
200         if( id != NULL ) {
201                 ber_bvfree( id );
202         }
203
204         if( new != NULL ) {
205                 ber_bvfree( new );
206         }
207
208         if( hash != NULL ) {
209                 ber_bvfree( hash );
210         }
211
212         if( ltid != NULL ) {
213                 txn_abort( ltid );
214                 op->o_private = NULL;
215         }
216
217         return rc;
218 }