Fix include paths to new location of libutil.
[garming/samba-autobuild/.git] / source4 / rpc_server / samr / samr_password.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    samr server password set/change handling
5
6    Copyright (C) Andrew Tridgell 2004
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "rpc_server/dcerpc_server.h"
25 #include "rpc_server/common/common.h"
26 #include "rpc_server/samr/dcesrv_samr.h"
27 #include "system/time.h"
28 #include "../lib/crypto/crypto.h"
29 #include "dsdb/common/flags.h"
30 #include "libcli/ldap/ldap.h"
31 #include "dsdb/samdb/samdb.h"
32 #include "auth/auth.h"
33 #include "rpc_server/samr/proto.h"
34 #include "libcli/auth/libcli_auth.h"
35 #include "../lib/util/util_ldb.h"
36 #include "param/param.h"
37
38 /* 
39   samr_ChangePasswordUser 
40 */
41 NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, 
42                                         TALLOC_CTX *mem_ctx,
43                                         struct samr_ChangePasswordUser *r)
44 {
45         struct dcesrv_handle *h;
46         struct samr_account_state *a_state;
47         struct ldb_context *sam_ctx;
48         struct ldb_message **res, *msg;
49         int ret;
50         struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash;
51         struct samr_Password *lm_pwd, *nt_pwd;
52         NTSTATUS status = NT_STATUS_OK;
53         const char * const attrs[] = { "dBCSPwd", "unicodePwd" , NULL };
54
55         DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);
56
57         a_state = h->data;
58
59         /* basic sanity checking on parameters.  Do this before any database ops */
60         if (!r->in.lm_present || !r->in.nt_present ||
61             !r->in.old_lm_crypted || !r->in.new_lm_crypted ||
62             !r->in.old_nt_crypted || !r->in.new_nt_crypted) {
63                 /* we should really handle a change with lm not
64                    present */
65                 return NT_STATUS_INVALID_PARAMETER_MIX;
66         }
67
68         /* To change a password we need to open as system */
69         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
70         if (sam_ctx == NULL) {
71                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
72         }
73
74         ret = ldb_transaction_start(sam_ctx);
75         if (ret) {
76                 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
77                 return NT_STATUS_TRANSACTION_ABORTED;
78         }
79
80         /* fetch the old hashes */
81         ret = gendb_search_dn(sam_ctx, mem_ctx,
82                               a_state->account_dn, &res, attrs);
83         if (ret != 1) {
84                 ldb_transaction_cancel(sam_ctx);
85                 return NT_STATUS_WRONG_PASSWORD;
86         }
87         msg = res[0];
88
89         status = samdb_result_passwords(mem_ctx, msg, &lm_pwd, &nt_pwd);
90         if (!NT_STATUS_IS_OK(status) || !lm_pwd || !nt_pwd) {
91                 ldb_transaction_cancel(sam_ctx);
92                 return NT_STATUS_WRONG_PASSWORD;
93         }
94
95         /* decrypt and check the new lm hash */
96         D_P16(lm_pwd->hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash);
97         D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash);
98         if (memcmp(checkHash.hash, lm_pwd, 16) != 0) {
99                 ldb_transaction_cancel(sam_ctx);
100                 return NT_STATUS_WRONG_PASSWORD;
101         }
102
103         /* decrypt and check the new nt hash */
104         D_P16(nt_pwd->hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash);
105         D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash);
106         if (memcmp(checkHash.hash, nt_pwd, 16) != 0) {
107                 ldb_transaction_cancel(sam_ctx);
108                 return NT_STATUS_WRONG_PASSWORD;
109         }
110         
111         /* The NT Cross is not required by Win2k3 R2, but if present
112            check the nt cross hash */
113         if (r->in.cross1_present && r->in.nt_cross) {
114                 D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash);
115                 if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
116                         ldb_transaction_cancel(sam_ctx);
117                         return NT_STATUS_WRONG_PASSWORD;
118                 }
119         }
120
121         /* The LM Cross is not required by Win2k3 R2, but if present
122            check the lm cross hash */
123         if (r->in.cross2_present && r->in.lm_cross) {
124                 D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash);
125                 if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
126                         ldb_transaction_cancel(sam_ctx);
127                         return NT_STATUS_WRONG_PASSWORD;
128                 }
129         }
130
131         msg = ldb_msg_new(mem_ctx);
132         if (msg == NULL) {
133                 ldb_transaction_cancel(sam_ctx);
134                 return NT_STATUS_NO_MEMORY;
135         }
136
137         msg->dn = ldb_dn_copy(msg, a_state->account_dn);
138         if (!msg->dn) {
139                 ldb_transaction_cancel(sam_ctx);
140                 return NT_STATUS_NO_MEMORY;
141         }
142
143         /* setup password modify mods on the user DN specified.  This may fail
144          * due to password policies.  */
145         status = samdb_set_password(sam_ctx, mem_ctx,
146                                     a_state->account_dn, a_state->domain_state->domain_dn,
147                                     msg, NULL, &new_lmPwdHash, &new_ntPwdHash, 
148                                     true, /* this is a user password change */
149                                     NULL,
150                                     NULL);
151         if (!NT_STATUS_IS_OK(status)) {
152                 ldb_transaction_cancel(sam_ctx);
153                 return status;
154         }
155
156         /* The above call only setup the modifications, this actually
157          * makes the write to the database. */
158         ret = samdb_replace(sam_ctx, mem_ctx, msg);
159         if (ret != 0) {
160                 DEBUG(2,("Failed to modify record to change password on %s: %s\n",
161                          ldb_dn_get_linearized(a_state->account_dn),
162                          ldb_errstring(sam_ctx)));
163                 ldb_transaction_cancel(sam_ctx);
164                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
165         }
166
167         /* And this confirms it in a transaction commit */
168         ret = ldb_transaction_commit(sam_ctx);
169         if (ret != 0) {
170                 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
171                          ldb_dn_get_linearized(a_state->account_dn),
172                          ldb_errstring(sam_ctx)));
173                 return NT_STATUS_TRANSACTION_ABORTED;
174         }
175
176         return NT_STATUS_OK;
177 }
178
179 /* 
180   samr_OemChangePasswordUser2 
181 */
182 NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
183                                      struct samr_OemChangePasswordUser2 *r)
184 {
185         NTSTATUS status;
186         char new_pass[512];
187         uint32_t new_pass_len;
188         struct samr_CryptPassword *pwbuf = r->in.password;
189         struct ldb_context *sam_ctx;
190         struct ldb_dn *user_dn;
191         int ret;
192         struct ldb_message **res, *mod;
193         const char * const attrs[] = { "objectSid", "dBCSPwd", NULL };
194         struct samr_Password *lm_pwd;
195         DATA_BLOB lm_pwd_blob;
196         uint8_t new_lm_hash[16];
197         struct samr_Password lm_verifier;
198
199         if (pwbuf == NULL) {
200                 return NT_STATUS_INVALID_PARAMETER;
201         }
202
203         if (r->in.hash == NULL) {
204                 return NT_STATUS_INVALID_PARAMETER;
205         }
206
207         /* To change a password we need to open as system */
208         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
209         if (sam_ctx == NULL) {
210                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
211         }
212
213         ret = ldb_transaction_start(sam_ctx);
214         if (ret) {
215                 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
216                 return NT_STATUS_TRANSACTION_ABORTED;
217         }
218
219         /* we need the users dn and the domain dn (derived from the
220            user SID). We also need the current lm password hash in
221            order to decrypt the incoming password */
222         ret = gendb_search(sam_ctx, 
223                            mem_ctx, NULL, &res, attrs,
224                            "(&(sAMAccountName=%s)(objectclass=user))",
225                            r->in.account->string);
226         if (ret != 1) {
227                 ldb_transaction_cancel(sam_ctx);
228                 /* Don't give the game away:  (don't allow anonymous users to prove the existance of usernames) */
229                 return NT_STATUS_WRONG_PASSWORD;
230         }
231
232         user_dn = res[0]->dn;
233
234         status = samdb_result_passwords(mem_ctx, res[0], &lm_pwd, NULL);
235         if (!NT_STATUS_IS_OK(status) || !lm_pwd) {
236                 ldb_transaction_cancel(sam_ctx);
237                 return NT_STATUS_WRONG_PASSWORD;
238         }
239
240         /* decrypt the password we have been given */
241         lm_pwd_blob = data_blob(lm_pwd->hash, sizeof(lm_pwd->hash)); 
242         arcfour_crypt_blob(pwbuf->data, 516, &lm_pwd_blob);
243         data_blob_free(&lm_pwd_blob);
244         
245         if (!decode_pw_buffer(pwbuf->data, new_pass, sizeof(new_pass),
246                               STR_ASCII)) {
247                 ldb_transaction_cancel(sam_ctx);
248                 DEBUG(3,("samr: failed to decode password buffer\n"));
249                 return NT_STATUS_WRONG_PASSWORD;
250         }
251
252         /* check LM verifier */
253         if (lm_pwd == NULL) {
254                 ldb_transaction_cancel(sam_ctx);
255                 return NT_STATUS_WRONG_PASSWORD;
256         }
257
258         E_deshash(new_pass, new_lm_hash);
259         E_old_pw_hash(new_lm_hash, lm_pwd->hash, lm_verifier.hash);
260         if (memcmp(lm_verifier.hash, r->in.hash->hash, 16) != 0) {
261                 ldb_transaction_cancel(sam_ctx);
262                 return NT_STATUS_WRONG_PASSWORD;
263         }
264
265         mod = ldb_msg_new(mem_ctx);
266         if (mod == NULL) {
267                 ldb_transaction_cancel(sam_ctx);
268                 return NT_STATUS_NO_MEMORY;
269         }
270
271         mod->dn = ldb_dn_copy(mod, user_dn);
272         if (!mod->dn) {
273                 ldb_transaction_cancel(sam_ctx);
274                 return NT_STATUS_NO_MEMORY;
275         }
276
277         /* set the password on the user DN specified.  This may fail
278          * due to password policies */
279         status = samdb_set_password(sam_ctx, mem_ctx,
280                                     user_dn, NULL, 
281                                     mod, new_pass, 
282                                     NULL, NULL,
283                                     true, /* this is a user password change */
284                                     NULL, 
285                                     NULL);
286         if (!NT_STATUS_IS_OK(status)) {
287                 ldb_transaction_cancel(sam_ctx);
288                 return status;
289         }
290
291         /* The above call only setup the modifications, this actually
292          * makes the write to the database. */
293         ret = samdb_replace(sam_ctx, mem_ctx, mod);
294         if (ret != 0) {
295                 DEBUG(2,("Failed to modify record to change password on %s: %s\n",
296                          ldb_dn_get_linearized(user_dn),
297                          ldb_errstring(sam_ctx)));
298                 ldb_transaction_cancel(sam_ctx);
299                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
300         }
301
302         /* And this confirms it in a transaction commit */
303         ret = ldb_transaction_commit(sam_ctx);
304         if (ret != 0) {
305                 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
306                          ldb_dn_get_linearized(user_dn),
307                          ldb_errstring(sam_ctx)));
308                 return NT_STATUS_TRANSACTION_ABORTED;
309         }
310
311         return NT_STATUS_OK;
312 }
313
314
315 /* 
316   samr_ChangePasswordUser3 
317 */
318 NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, 
319                                   TALLOC_CTX *mem_ctx,
320                                   struct samr_ChangePasswordUser3 *r)
321 {       
322         NTSTATUS status;
323         char new_pass[512];
324         struct ldb_context *sam_ctx = NULL;
325         struct ldb_dn *user_dn;
326         int ret;
327         struct ldb_message **res, *mod;
328         const char * const attrs[] = { "unicodePwd", "dBCSPwd", NULL };
329         struct samr_Password *nt_pwd, *lm_pwd;
330         DATA_BLOB nt_pwd_blob;
331         struct samr_DomInfo1 *dominfo = NULL;
332         struct samr_ChangeReject *reject = NULL;
333         enum samr_RejectReason reason = SAMR_REJECT_OTHER;
334         uint8_t new_nt_hash[16], new_lm_hash[16];
335         struct samr_Password nt_verifier, lm_verifier;
336
337         ZERO_STRUCT(r->out);
338
339         if (r->in.nt_password == NULL ||
340             r->in.nt_verifier == NULL) {
341                 return NT_STATUS_INVALID_PARAMETER;
342         }
343
344         /* To change a password we need to open as system */
345         sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
346         if (sam_ctx == NULL) {
347                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
348         }
349
350         ret = ldb_transaction_start(sam_ctx);
351         if (ret) {
352                 talloc_free(sam_ctx);
353                 DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
354                 return NT_STATUS_TRANSACTION_ABORTED;
355         }
356
357         /* we need the users dn and the domain dn (derived from the
358            user SID). We also need the current lm and nt password hashes
359            in order to decrypt the incoming passwords */
360         ret = gendb_search(sam_ctx, 
361                            mem_ctx, NULL, &res, attrs,
362                            "(&(sAMAccountName=%s)(objectclass=user))",
363                            r->in.account->string);
364         if (ret != 1) {
365                 /* Don't give the game away:  (don't allow anonymous users to prove the existance of usernames) */
366                 status = NT_STATUS_WRONG_PASSWORD;
367                 goto failed;
368         }
369
370         user_dn = res[0]->dn;
371
372         status = samdb_result_passwords(mem_ctx, res[0], &lm_pwd, &nt_pwd);
373         if (!NT_STATUS_IS_OK(status) ) {
374                 goto failed;
375         }
376
377         if (!nt_pwd) {
378                 status = NT_STATUS_WRONG_PASSWORD;
379                 goto failed;
380         }
381
382         /* decrypt the password we have been given */
383         nt_pwd_blob = data_blob(nt_pwd->hash, sizeof(nt_pwd->hash));
384         arcfour_crypt_blob(r->in.nt_password->data, 516, &nt_pwd_blob);
385         data_blob_free(&nt_pwd_blob);
386
387         if (!decode_pw_buffer(r->in.nt_password->data, new_pass, sizeof(new_pass),
388                               STR_UNICODE)) {
389                 DEBUG(3,("samr: failed to decode password buffer\n"));
390                 status = NT_STATUS_WRONG_PASSWORD;
391                 goto failed;
392         }
393
394         if (r->in.nt_verifier == NULL) {
395                 status = NT_STATUS_WRONG_PASSWORD;
396                 goto failed;
397         }
398
399         /* check NT verifier */
400         E_md4hash(new_pass, new_nt_hash);
401         E_old_pw_hash(new_nt_hash, nt_pwd->hash, nt_verifier.hash);
402         if (memcmp(nt_verifier.hash, r->in.nt_verifier->hash, 16) != 0) {
403                 status = NT_STATUS_WRONG_PASSWORD;
404                 goto failed;
405         }
406
407         /* check LM verifier */
408         if (lm_pwd && r->in.lm_verifier != NULL) {
409                 E_deshash(new_pass, new_lm_hash);
410                 E_old_pw_hash(new_nt_hash, lm_pwd->hash, lm_verifier.hash);
411                 if (memcmp(lm_verifier.hash, r->in.lm_verifier->hash, 16) != 0) {
412                         status = NT_STATUS_WRONG_PASSWORD;
413                         goto failed;
414                 }
415         }
416
417
418         mod = ldb_msg_new(mem_ctx);
419         if (mod == NULL) {
420                 return NT_STATUS_NO_MEMORY;
421         }
422
423         mod->dn = ldb_dn_copy(mod, user_dn);
424         if (!mod->dn) {
425                 status = NT_STATUS_NO_MEMORY;
426                 goto failed;
427         }
428
429         /* set the password on the user DN specified.  This may fail
430          * due to password policies */
431         status = samdb_set_password(sam_ctx, mem_ctx,
432                                     user_dn, NULL, 
433                                     mod, new_pass, 
434                                     NULL, NULL,
435                                     true, /* this is a user password change */
436                                     &reason, 
437                                     &dominfo);
438         if (!NT_STATUS_IS_OK(status)) {
439                 goto failed;
440         }
441
442         /* The above call only setup the modifications, this actually
443          * makes the write to the database. */
444         ret = samdb_replace(sam_ctx, mem_ctx, mod);
445         if (ret != 0) {
446                 DEBUG(2,("samdb_replace failed to change password for %s: %s\n",
447                          ldb_dn_get_linearized(user_dn),
448                          ldb_errstring(sam_ctx)));
449                 status = NT_STATUS_UNSUCCESSFUL;
450                 goto failed;
451         }
452
453         /* And this confirms it in a transaction commit */
454         ret = ldb_transaction_commit(sam_ctx);
455         if (ret != 0) {
456                 DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
457                          ldb_dn_get_linearized(user_dn),
458                          ldb_errstring(sam_ctx)));
459                 status = NT_STATUS_TRANSACTION_ABORTED;
460                 goto failed;
461         }
462
463         return NT_STATUS_OK;
464
465 failed:
466         ldb_transaction_cancel(sam_ctx);
467         talloc_free(sam_ctx);
468
469         reject = talloc(mem_ctx, struct samr_ChangeReject);
470         r->out.dominfo = dominfo;
471         r->out.reject = reject;
472
473         if (reject == NULL) {
474                 return status;
475         }
476         ZERO_STRUCTP(reject);
477
478         reject->reason = reason;
479
480         return status;
481 }
482
483
484 /* 
485   samr_ChangePasswordUser2 
486
487   easy - just a subset of samr_ChangePasswordUser3
488 */
489 NTSTATUS dcesrv_samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
490                                   struct samr_ChangePasswordUser2 *r)
491 {
492         struct samr_ChangePasswordUser3 r2;
493
494         r2.in.server = r->in.server;
495         r2.in.account = r->in.account;
496         r2.in.nt_password = r->in.nt_password;
497         r2.in.nt_verifier = r->in.nt_verifier;
498         r2.in.lm_change = r->in.lm_change;
499         r2.in.lm_password = r->in.lm_password;
500         r2.in.lm_verifier = r->in.lm_verifier;
501         r2.in.password3 = NULL;
502
503         return dcesrv_samr_ChangePasswordUser3(dce_call, mem_ctx, &r2);
504 }
505
506
507 /*
508   set password via a samr_CryptPassword buffer
509   this will in the 'msg' with modify operations that will update the user
510   password when applied
511 */
512 NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call,
513                            void *sam_ctx,
514                            struct ldb_dn *account_dn, struct ldb_dn *domain_dn,
515                            TALLOC_CTX *mem_ctx,
516                            struct ldb_message *msg, 
517                            struct samr_CryptPassword *pwbuf)
518 {
519         NTSTATUS nt_status;
520         char new_pass[512];
521         DATA_BLOB session_key = data_blob(NULL, 0);
522
523         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
524         if (!NT_STATUS_IS_OK(nt_status)) {
525                 return nt_status;
526         }
527
528         arcfour_crypt_blob(pwbuf->data, 516, &session_key);
529
530         if (!decode_pw_buffer(pwbuf->data, new_pass, sizeof(new_pass),
531                               STR_UNICODE)) {
532                 DEBUG(3,("samr: failed to decode password buffer\n"));
533                 return NT_STATUS_WRONG_PASSWORD;
534         }
535
536         /* set the password - samdb needs to know both the domain and user DNs,
537            so the domain password policy can be used */
538         return samdb_set_password(sam_ctx, mem_ctx,
539                                   account_dn, domain_dn, 
540                                   msg, new_pass, 
541                                   NULL, NULL,
542                                   false, /* This is a password set, not change */
543                                   NULL, NULL);
544 }
545
546
547 /*
548   set password via a samr_CryptPasswordEx buffer
549   this will in the 'msg' with modify operations that will update the user
550   password when applied
551 */
552 NTSTATUS samr_set_password_ex(struct dcesrv_call_state *dce_call,
553                               struct ldb_context *sam_ctx,
554                               struct ldb_dn *account_dn, struct ldb_dn *domain_dn,
555                               TALLOC_CTX *mem_ctx,
556                               struct ldb_message *msg, 
557                               struct samr_CryptPasswordEx *pwbuf)
558 {
559         NTSTATUS nt_status;
560         char new_pass[512];
561         uint32_t new_pass_len;
562         DATA_BLOB co_session_key;
563         DATA_BLOB session_key = data_blob(NULL, 0);
564         struct MD5Context ctx;
565
566         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
567         if (!NT_STATUS_IS_OK(nt_status)) {
568                 return nt_status;
569         }
570
571         co_session_key = data_blob_talloc(mem_ctx, NULL, 16);
572         if (!co_session_key.data) {
573                 return NT_STATUS_NO_MEMORY;
574         }
575
576         MD5Init(&ctx);
577         MD5Update(&ctx, &pwbuf->data[516], 16);
578         MD5Update(&ctx, session_key.data, session_key.length);
579         MD5Final(co_session_key.data, &ctx);
580         
581         arcfour_crypt_blob(pwbuf->data, 516, &co_session_key);
582
583         if (!decode_pw_buffer(pwbuf->data, new_pass, sizeof(new_pass),
584                               STR_UNICODE)) {
585                 DEBUG(3,("samr: failed to decode password buffer\n"));
586                 return NT_STATUS_WRONG_PASSWORD;
587         }
588
589         /* set the password - samdb needs to know both the domain and user DNs,
590            so the domain password policy can be used */
591         return samdb_set_password(sam_ctx, mem_ctx,
592                                   account_dn, domain_dn, 
593                                   msg, new_pass, 
594                                   NULL, NULL,
595                                   false, /* This is a password set, not change */
596                                   NULL, NULL);
597 }
598
599