source: vendor/current/source3/passdb/pdb_nds.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 22.1 KB
Line 
1/*
2 Unix SMB/CIFS mplementation.
3 NDS LDAP helper functions for SAMBA
4 Copyright (C) Vince Brimhall 2004-2005
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19*/
20
21#include "includes.h"
22#include "passdb.h"
23
24#include <lber.h>
25#include <ldap.h>
26
27#include "smbldap.h"
28#include "passdb/pdb_ldap.h"
29#include "passdb/pdb_nds.h"
30
31#define NMASLDAP_GET_LOGIN_CONFIG_REQUEST "2.16.840.1.113719.1.39.42.100.3"
32#define NMASLDAP_GET_LOGIN_CONFIG_RESPONSE "2.16.840.1.113719.1.39.42.100.4"
33#define NMASLDAP_SET_PASSWORD_REQUEST "2.16.840.1.113719.1.39.42.100.11"
34#define NMASLDAP_SET_PASSWORD_RESPONSE "2.16.840.1.113719.1.39.42.100.12"
35#define NMASLDAP_GET_PASSWORD_REQUEST "2.16.840.1.113719.1.39.42.100.13"
36#define NMASLDAP_GET_PASSWORD_RESPONSE "2.16.840.1.113719.1.39.42.100.14"
37
38#define NMAS_LDAP_EXT_VERSION 1
39
40/**********************************************************************
41 Take the request BER value and input data items and BER encodes the
42 data into the BER value
43**********************************************************************/
44
45static int berEncodePasswordData(
46 struct berval **requestBV,
47 const char *objectDN,
48 const char *password,
49 const char *password2)
50{
51 int err = 0, rc=0;
52 BerElement *requestBer = NULL;
53
54 const char * utf8ObjPtr = NULL;
55 int utf8ObjSize = 0;
56 const char * utf8PwdPtr = NULL;
57 int utf8PwdSize = 0;
58 const char * utf8Pwd2Ptr = NULL;
59 int utf8Pwd2Size = 0;
60
61
62 /* Convert objectDN and tag strings from Unicode to UTF-8 */
63 utf8ObjSize = strlen(objectDN)+1;
64 utf8ObjPtr = objectDN;
65
66 if (password != NULL)
67 {
68 utf8PwdSize = strlen(password)+1;
69 utf8PwdPtr = password;
70 }
71
72 if (password2 != NULL)
73 {
74 utf8Pwd2Size = strlen(password2)+1;
75 utf8Pwd2Ptr = password2;
76 }
77
78 /* Allocate a BerElement for the request parameters. */
79 if((requestBer = ber_alloc()) == NULL)
80 {
81 err = LDAP_ENCODING_ERROR;
82 goto Cleanup;
83 }
84
85 if (password != NULL && password2 != NULL)
86 {
87 /* BER encode the NMAS Version, the objectDN, and the password */
88 rc = ber_printf(requestBer, "{iooo}", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize, utf8PwdPtr, utf8PwdSize, utf8Pwd2Ptr, utf8Pwd2Size);
89 }
90 else if (password != NULL)
91 {
92 /* BER encode the NMAS Version, the objectDN, and the password */
93 rc = ber_printf(requestBer, "{ioo}", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize, utf8PwdPtr, utf8PwdSize);
94 }
95 else
96 {
97 /* BER encode the NMAS Version and the objectDN */
98 rc = ber_printf(requestBer, "{io}", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize);
99 }
100
101 if (rc < 0)
102 {
103 err = LDAP_ENCODING_ERROR;
104 goto Cleanup;
105 }
106 else
107 {
108 err = 0;
109 }
110
111 /* Convert the BER we just built to a berval that we'll send with the extended request. */
112 if(ber_flatten(requestBer, requestBV) == LBER_ERROR)
113 {
114 err = LDAP_ENCODING_ERROR;
115 goto Cleanup;
116 }
117
118Cleanup:
119
120 if(requestBer)
121 {
122 ber_free(requestBer, 1);
123 }
124
125 return err;
126}
127
128/**********************************************************************
129 Take the request BER value and input data items and BER encodes the
130 data into the BER value
131**********************************************************************/
132
133static int berEncodeLoginData(
134 struct berval **requestBV,
135 char *objectDN,
136 unsigned int methodIDLen,
137 unsigned int *methodID,
138 char *tag,
139 size_t putDataLen,
140 void *putData)
141{
142 int err = 0;
143 BerElement *requestBer = NULL;
144
145 unsigned int i;
146 unsigned int elemCnt = methodIDLen / sizeof(unsigned int);
147
148 char *utf8ObjPtr=NULL;
149 int utf8ObjSize = 0;
150
151 char *utf8TagPtr = NULL;
152 int utf8TagSize = 0;
153
154 utf8ObjPtr = objectDN;
155 utf8ObjSize = strlen(utf8ObjPtr)+1;
156
157 utf8TagPtr = tag;
158 utf8TagSize = strlen(utf8TagPtr)+1;
159
160 /* Allocate a BerElement for the request parameters. */
161 if((requestBer = ber_alloc()) == NULL)
162 {
163 err = LDAP_ENCODING_ERROR;
164 goto Cleanup;
165 }
166
167 /* BER encode the NMAS Version and the objectDN */
168 err = (ber_printf(requestBer, "{io", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize) < 0) ? LDAP_ENCODING_ERROR : 0;
169
170 /* BER encode the MethodID Length and value */
171 if (!err)
172 {
173 err = (ber_printf(requestBer, "{i{", methodIDLen) < 0) ? LDAP_ENCODING_ERROR : 0;
174 }
175
176 for (i = 0; !err && i < elemCnt; i++)
177 {
178 err = (ber_printf(requestBer, "i", methodID[i]) < 0) ? LDAP_ENCODING_ERROR : 0;
179 }
180
181 if (!err)
182 {
183 err = (ber_printf(requestBer, "}}", 0) < 0) ? LDAP_ENCODING_ERROR : 0;
184 }
185
186 if(putData)
187 {
188 /* BER Encode the the tag and data */
189 err = (ber_printf(requestBer, "oio}", utf8TagPtr, utf8TagSize, putDataLen, putData, putDataLen) < 0) ? LDAP_ENCODING_ERROR : 0;
190 }
191 else
192 {
193 /* BER Encode the the tag */
194 err = (ber_printf(requestBer, "o}", utf8TagPtr, utf8TagSize) < 0) ? LDAP_ENCODING_ERROR : 0;
195 }
196
197 if (err)
198 {
199 goto Cleanup;
200 }
201
202 /* Convert the BER we just built to a berval that we'll send with the extended request. */
203 if(ber_flatten(requestBer, requestBV) == LBER_ERROR)
204 {
205 err = LDAP_ENCODING_ERROR;
206 goto Cleanup;
207 }
208
209Cleanup:
210
211 if(requestBer)
212 {
213 ber_free(requestBer, 1);
214 }
215
216 return err;
217}
218
219/**********************************************************************
220 Takes the reply BER Value and decodes the NMAS server version and
221 return code and if a non null retData buffer was supplied, tries to
222 decode the the return data and length
223**********************************************************************/
224
225static int berDecodeLoginData(
226 struct berval *replyBV,
227 int *serverVersion,
228 size_t *retDataLen,
229 void *retData )
230{
231 int err = 0;
232 BerElement *replyBer = NULL;
233 char *retOctStr = NULL;
234 size_t retOctStrLen = 0;
235
236 if((replyBer = ber_init(replyBV)) == NULL)
237 {
238 err = LDAP_OPERATIONS_ERROR;
239 goto Cleanup;
240 }
241
242 if(retData)
243 {
244 retOctStrLen = *retDataLen + 1;
245 retOctStr = SMB_MALLOC_ARRAY(char, retOctStrLen);
246 if(!retOctStr)
247 {
248 err = LDAP_OPERATIONS_ERROR;
249 goto Cleanup;
250 }
251
252 if(ber_scanf(replyBer, "{iis}", serverVersion, &err, retOctStr, &retOctStrLen) != -1)
253 {
254 if (*retDataLen >= retOctStrLen)
255 {
256 memcpy(retData, retOctStr, retOctStrLen);
257 }
258 else if (!err)
259 {
260 err = LDAP_NO_MEMORY;
261 }
262
263 *retDataLen = retOctStrLen;
264 }
265 else if (!err)
266 {
267 err = LDAP_DECODING_ERROR;
268 }
269 }
270 else
271 {
272 if(ber_scanf(replyBer, "{ii}", serverVersion, &err) == -1)
273 {
274 if (!err)
275 {
276 err = LDAP_DECODING_ERROR;
277 }
278 }
279 }
280
281Cleanup:
282
283 if(replyBer)
284 {
285 ber_free(replyBer, 1);
286 }
287
288 if (retOctStr != NULL)
289 {
290 memset(retOctStr, 0, retOctStrLen);
291 free(retOctStr);
292 }
293
294 return err;
295}
296
297/**********************************************************************
298 Retrieves data in the login configuration of the specified object
299 that is tagged with the specified methodID and tag.
300**********************************************************************/
301
302static int getLoginConfig(
303 LDAP *ld,
304 char *objectDN,
305 unsigned int methodIDLen,
306 unsigned int *methodID,
307 char *tag,
308 size_t *dataLen,
309 void *data )
310{
311 int err = 0;
312 struct berval *requestBV = NULL;
313 char *replyOID = NULL;
314 struct berval *replyBV = NULL;
315 int serverVersion = 0;
316
317 /* Validate unicode parameters. */
318 if((strlen(objectDN) == 0) || ld == NULL)
319 {
320 return LDAP_NO_SUCH_ATTRIBUTE;
321 }
322
323 err = berEncodeLoginData(&requestBV, objectDN, methodIDLen, methodID, tag, 0, NULL);
324 if(err)
325 {
326 goto Cleanup;
327 }
328
329 /* Call the ldap_extended_operation (synchronously) */
330 if((err = ldap_extended_operation_s(ld, NMASLDAP_GET_LOGIN_CONFIG_REQUEST,
331 requestBV, NULL, NULL, &replyOID, &replyBV)))
332 {
333 goto Cleanup;
334 }
335
336 /* Make sure there is a return OID */
337 if(!replyOID)
338 {
339 err = LDAP_NOT_SUPPORTED;
340 goto Cleanup;
341 }
342
343 /* Is this what we were expecting to get back. */
344 if(strcmp(replyOID, NMASLDAP_GET_LOGIN_CONFIG_RESPONSE))
345 {
346 err = LDAP_NOT_SUPPORTED;
347 goto Cleanup;
348 }
349
350 /* Do we have a good returned berval? */
351 if(!replyBV)
352 {
353 /* No; returned berval means we experienced a rather drastic error. */
354 /* Return operations error. */
355 err = LDAP_OPERATIONS_ERROR;
356 goto Cleanup;
357 }
358
359 err = berDecodeLoginData(replyBV, &serverVersion, dataLen, data);
360
361 if(serverVersion != NMAS_LDAP_EXT_VERSION)
362 {
363 err = LDAP_OPERATIONS_ERROR;
364 goto Cleanup;
365 }
366
367Cleanup:
368
369 if(replyBV)
370 {
371 ber_bvfree(replyBV);
372 }
373
374 /* Free the return OID string if one was returned. */
375 if(replyOID)
376 {
377 ldap_memfree(replyOID);
378 }
379
380 /* Free memory allocated while building the request ber and berval. */
381 if(requestBV)
382 {
383 ber_bvfree(requestBV);
384 }
385
386 /* Return the appropriate error/success code. */
387 return err;
388}
389
390/**********************************************************************
391 Attempts to get the Simple Password
392**********************************************************************/
393
394static int nmasldap_get_simple_pwd(
395 LDAP *ld,
396 char *objectDN,
397 size_t pwdLen,
398 char *pwd )
399{
400 int err = 0;
401 unsigned int methodID = 0;
402 unsigned int methodIDLen = sizeof(methodID);
403 char tag[] = {'P','A','S','S','W','O','R','D',' ','H','A','S','H',0};
404 char *pwdBuf=NULL;
405 size_t pwdBufLen, bufferLen;
406
407 bufferLen = pwdBufLen = pwdLen+2;
408 pwdBuf = SMB_MALLOC_ARRAY(char, pwdBufLen); /* digest and null */
409 if(pwdBuf == NULL)
410 {
411 return LDAP_NO_MEMORY;
412 }
413
414 err = getLoginConfig(ld, objectDN, methodIDLen, &methodID, tag, &pwdBufLen, pwdBuf);
415 if (err == 0)
416 {
417 if (pwdBufLen !=0)
418 {
419 pwdBuf[pwdBufLen] = 0; /* null terminate */
420
421 switch (pwdBuf[0])
422 {
423 case 1: /* cleartext password */
424 break;
425 case 2: /* SHA1 HASH */
426 case 3: /* MD5_ID */
427 case 4: /* UNIXCrypt_ID */
428 case 8: /* SSHA_ID */
429 default: /* Unknown digest */
430 err = LDAP_INAPPROPRIATE_AUTH; /* only return clear text */
431 break;
432 }
433
434 if (!err)
435 {
436 if (pwdLen >= pwdBufLen-1)
437 {
438 memcpy(pwd, &pwdBuf[1], pwdBufLen-1); /* skip digest tag and include null */
439 }
440 else
441 {
442 err = LDAP_NO_MEMORY;
443 }
444 }
445 }
446 }
447
448 if (pwdBuf != NULL)
449 {
450 memset(pwdBuf, 0, bufferLen);
451 free(pwdBuf);
452 }
453
454 return err;
455}
456
457
458/**********************************************************************
459 Attempts to set the Universal Password
460**********************************************************************/
461
462static int nmasldap_set_password(
463 LDAP *ld,
464 const char *objectDN,
465 const char *pwd )
466{
467 int err = 0;
468
469 struct berval *requestBV = NULL;
470 char *replyOID = NULL;
471 struct berval *replyBV = NULL;
472 int serverVersion;
473
474 /* Validate char parameters. */
475 if(objectDN == NULL || (strlen(objectDN) == 0) || pwd == NULL || ld == NULL)
476 {
477 return LDAP_NO_SUCH_ATTRIBUTE;
478 }
479
480 err = berEncodePasswordData(&requestBV, objectDN, pwd, NULL);
481 if(err)
482 {
483 goto Cleanup;
484 }
485
486 /* Call the ldap_extended_operation (synchronously) */
487 if((err = ldap_extended_operation_s(ld, NMASLDAP_SET_PASSWORD_REQUEST, requestBV, NULL, NULL, &replyOID, &replyBV)))
488 {
489 goto Cleanup;
490 }
491
492 /* Make sure there is a return OID */
493 if(!replyOID)
494 {
495 err = LDAP_NOT_SUPPORTED;
496 goto Cleanup;
497 }
498
499 /* Is this what we were expecting to get back. */
500 if(strcmp(replyOID, NMASLDAP_SET_PASSWORD_RESPONSE))
501 {
502 err = LDAP_NOT_SUPPORTED;
503 goto Cleanup;
504 }
505
506 /* Do we have a good returned berval? */
507 if(!replyBV)
508 {
509 /* No; returned berval means we experienced a rather drastic error. */
510 /* Return operations error. */
511 err = LDAP_OPERATIONS_ERROR;
512 goto Cleanup;
513 }
514
515 err = berDecodeLoginData(replyBV, &serverVersion, NULL, NULL);
516
517 if(serverVersion != NMAS_LDAP_EXT_VERSION)
518 {
519 err = LDAP_OPERATIONS_ERROR;
520 goto Cleanup;
521 }
522
523Cleanup:
524
525 if(replyBV)
526 {
527 ber_bvfree(replyBV);
528 }
529
530 /* Free the return OID string if one was returned. */
531 if(replyOID)
532 {
533 ldap_memfree(replyOID);
534 }
535
536 /* Free memory allocated while building the request ber and berval. */
537 if(requestBV)
538 {
539 ber_bvfree(requestBV);
540 }
541
542 /* Return the appropriate error/success code. */
543 return err;
544}
545
546/**********************************************************************
547 Attempts to get the Universal Password
548**********************************************************************/
549
550static int nmasldap_get_password(
551 LDAP *ld,
552 char *objectDN,
553 size_t *pwdSize, /* in bytes */
554 unsigned char *pwd )
555{
556 int err = 0;
557
558 struct berval *requestBV = NULL;
559 char *replyOID = NULL;
560 struct berval *replyBV = NULL;
561 int serverVersion;
562 char *pwdBuf;
563 size_t pwdBufLen, bufferLen;
564
565 /* Validate char parameters. */
566 if(objectDN == NULL || (strlen(objectDN) == 0) || pwdSize == NULL || ld == NULL)
567 {
568 return LDAP_NO_SUCH_ATTRIBUTE;
569 }
570
571 bufferLen = pwdBufLen = *pwdSize;
572 pwdBuf = SMB_MALLOC_ARRAY(char, pwdBufLen+2);
573 if(pwdBuf == NULL)
574 {
575 return LDAP_NO_MEMORY;
576 }
577
578 err = berEncodePasswordData(&requestBV, objectDN, NULL, NULL);
579 if(err)
580 {
581 goto Cleanup;
582 }
583
584 /* Call the ldap_extended_operation (synchronously) */
585 if((err = ldap_extended_operation_s(ld, NMASLDAP_GET_PASSWORD_REQUEST, requestBV, NULL, NULL, &replyOID, &replyBV)))
586 {
587 goto Cleanup;
588 }
589
590 /* Make sure there is a return OID */
591 if(!replyOID)
592 {
593 err = LDAP_NOT_SUPPORTED;
594 goto Cleanup;
595 }
596
597 /* Is this what we were expecting to get back. */
598 if(strcmp(replyOID, NMASLDAP_GET_PASSWORD_RESPONSE))
599 {
600 err = LDAP_NOT_SUPPORTED;
601 goto Cleanup;
602 }
603
604 /* Do we have a good returned berval? */
605 if(!replyBV)
606 {
607 /* No; returned berval means we experienced a rather drastic error. */
608 /* Return operations error. */
609 err = LDAP_OPERATIONS_ERROR;
610 goto Cleanup;
611 }
612
613 err = berDecodeLoginData(replyBV, &serverVersion, &pwdBufLen, pwdBuf);
614
615 if(serverVersion != NMAS_LDAP_EXT_VERSION)
616 {
617 err = LDAP_OPERATIONS_ERROR;
618 goto Cleanup;
619 }
620
621 if (!err && pwdBufLen != 0)
622 {
623 if (*pwdSize >= pwdBufLen+1 && pwd != NULL)
624 {
625 memcpy(pwd, pwdBuf, pwdBufLen);
626 pwd[pwdBufLen] = 0; /* add null termination */
627 }
628 *pwdSize = pwdBufLen; /* does not include null termination */
629 }
630
631Cleanup:
632
633 if(replyBV)
634 {
635 ber_bvfree(replyBV);
636 }
637
638 /* Free the return OID string if one was returned. */
639 if(replyOID)
640 {
641 ldap_memfree(replyOID);
642 }
643
644 /* Free memory allocated while building the request ber and berval. */
645 if(requestBV)
646 {
647 ber_bvfree(requestBV);
648 }
649
650 if (pwdBuf != NULL)
651 {
652 memset(pwdBuf, 0, bufferLen);
653 free(pwdBuf);
654 }
655
656 /* Return the appropriate error/success code. */
657 return err;
658}
659
660/**********************************************************************
661 Get the user's password from NDS.
662 *********************************************************************/
663
664int pdb_nds_get_password(
665 struct smbldap_state *ldap_state,
666 char *object_dn,
667 size_t *pwd_len,
668 char *pwd )
669{
670 LDAP *ld = ldap_state->ldap_struct;
671 int rc = -1;
672
673 rc = nmasldap_get_password(ld, object_dn, pwd_len, (unsigned char *)pwd);
674 if (rc == LDAP_SUCCESS) {
675#ifdef DEBUG_PASSWORD
676 DEBUG(100,("nmasldap_get_password returned %s for %s\n", pwd, object_dn));
677#endif
678 DEBUG(5, ("NDS Universal Password retrieved for %s\n", object_dn));
679 } else {
680 DEBUG(3, ("NDS Universal Password NOT retrieved for %s\n", object_dn));
681 }
682
683 if (rc != LDAP_SUCCESS) {
684 rc = nmasldap_get_simple_pwd(ld, object_dn, *pwd_len, pwd);
685 if (rc == LDAP_SUCCESS) {
686#ifdef DEBUG_PASSWORD
687 DEBUG(100,("nmasldap_get_simple_pwd returned %s for %s\n", pwd, object_dn));
688#endif
689 DEBUG(5, ("NDS Simple Password retrieved for %s\n", object_dn));
690 } else {
691 /* We couldn't get the password */
692 DEBUG(3, ("NDS Simple Password NOT retrieved for %s\n", object_dn));
693 return LDAP_INVALID_CREDENTIALS;
694 }
695 }
696
697 /* We got the password */
698 return LDAP_SUCCESS;
699}
700
701/**********************************************************************
702 Set the users NDS, Universal and Simple passwords.
703 ********************************************************************/
704
705int pdb_nds_set_password(
706 struct smbldap_state *ldap_state,
707 char *object_dn,
708 const char *pwd )
709{
710 LDAP *ld = ldap_state->ldap_struct;
711 int rc = -1;
712 LDAPMod **tmpmods = NULL;
713
714 rc = nmasldap_set_password(ld, object_dn, pwd);
715 if (rc == LDAP_SUCCESS) {
716 DEBUG(5,("NDS Universal Password changed for user %s\n", object_dn));
717 } else {
718 char *ld_error = NULL;
719 ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &ld_error);
720
721 /* This will fail if Universal Password is not enabled for the user's context */
722 DEBUG(3,("NDS Universal Password could not be changed for user %s: %s (%s)\n",
723 object_dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
724 SAFE_FREE(ld_error);
725 }
726
727 /* Set eDirectory Password */
728 smbldap_set_mod(&tmpmods, LDAP_MOD_REPLACE, "userPassword", pwd);
729 rc = smbldap_modify(ldap_state, object_dn, tmpmods);
730
731 return rc;
732}
733
734/**********************************************************************
735 Allow ldap server to update internal login attempt counters by
736 performing a simple bind. If the samba authentication failed attempt
737 the bind with a bogus, randomly generated password to count the
738 failed attempt. If the bind fails even though samba authentication
739 succeeded, this would indicate that the user's account is disabled,
740 time restrictions are in place or some other password policy
741 violation.
742*********************************************************************/
743
744static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
745 struct samu *sam_acct, bool success)
746{
747 struct ldapsam_privates *ldap_state;
748
749 if ((!methods) || (!sam_acct)) {
750 DEBUG(3,("pdb_nds_update_login_attempts: invalid parameter.\n"));
751 return NT_STATUS_MEMORY_NOT_ALLOCATED;
752 }
753
754 ldap_state = (struct ldapsam_privates *)methods->private_data;
755
756 if (ldap_state) {
757 /* Attempt simple bind with user credentials to update eDirectory
758 password policy */
759 int rc = 0;
760 char *dn;
761 LDAPMessage *result = NULL;
762 LDAPMessage *entry = NULL;
763 const char **attr_list;
764 size_t pwd_len;
765 char clear_text_pw[512];
766 LDAP *ld = NULL;
767 const char *username = pdb_get_username(sam_acct);
768 bool got_clear_text_pw = False;
769
770 DEBUG(5,("pdb_nds_update_login_attempts: %s login for %s\n",
771 success ? "Successful" : "Failed", username));
772
773 result = (LDAPMessage *)pdb_get_backend_private_data(sam_acct, methods);
774 if (!result) {
775 attr_list = get_userattr_list(NULL,
776 ldap_state->schema_ver);
777 rc = ldapsam_search_suffix_by_name(ldap_state, username, &result, attr_list );
778 TALLOC_FREE( attr_list );
779 if (rc != LDAP_SUCCESS) {
780 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
781 }
782 pdb_set_backend_private_data(sam_acct, result, NULL,
783 methods, PDB_CHANGED);
784 smbldap_talloc_autofree_ldapmsg(sam_acct, result);
785 }
786
787 if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
788 DEBUG(0, ("pdb_nds_update_login_attempts: No user to modify!\n"));
789 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
790 }
791
792 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
793 dn = smbldap_talloc_dn(talloc_tos(), ldap_state->smbldap_state->ldap_struct, entry);
794 if (!dn) {
795 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
796 }
797
798 DEBUG(3, ("pdb_nds_update_login_attempts: username %s found dn '%s'\n", username, dn));
799
800 pwd_len = sizeof(clear_text_pw);
801 if (success == True) {
802 if (pdb_nds_get_password(ldap_state->smbldap_state, dn, &pwd_len, clear_text_pw) == LDAP_SUCCESS) {
803 /* Got clear text password. Use simple ldap bind */
804 got_clear_text_pw = True;
805 }
806 } else {
807 generate_random_buffer((unsigned char *)clear_text_pw, 24);
808 clear_text_pw[24] = '\0';
809 DEBUG(5,("pdb_nds_update_login_attempts: using random password %s\n", clear_text_pw));
810 }
811
812 if((success != True) || (got_clear_text_pw == True)) {
813
814 rc = smbldap_setup_full_conn(&ld, ldap_state->location);
815 if (rc) {
816 TALLOC_FREE(dn);
817 return NT_STATUS_INVALID_CONNECTION;
818 }
819
820 /* Attempt simple bind with real or bogus password */
821 rc = ldap_simple_bind_s(ld, dn, clear_text_pw);
822 ldap_unbind(ld);
823 if (rc == LDAP_SUCCESS) {
824 DEBUG(5,("pdb_nds_update_login_attempts: ldap_simple_bind_s Successful for %s\n", username));
825 } else {
826 NTSTATUS nt_status = NT_STATUS_ACCOUNT_RESTRICTION;
827 DEBUG(5,("pdb_nds_update_login_attempts: ldap_simple_bind_s Failed for %s\n", username));
828 switch(rc) {
829 case LDAP_INVALID_CREDENTIALS:
830 nt_status = NT_STATUS_WRONG_PASSWORD;
831 break;
832 case LDAP_UNWILLING_TO_PERFORM:
833 /* eDir returns this if the account was disabled. */
834 /* The problem is we don't know if the given
835 password was correct for this account or
836 not. We have to return more info than we
837 should and tell the client NT_STATUS_ACCOUNT_DISABLED
838 so they don't think the password was bad. JRA. */
839 nt_status = NT_STATUS_ACCOUNT_DISABLED;
840 break;
841 default:
842 break;
843 }
844 return nt_status;
845 }
846 }
847 TALLOC_FREE(dn);
848 }
849
850 return NT_STATUS_OK;
851}
852
853/**********************************************************************
854 Intitalise the parts of the pdb_methods structuire that are common
855 to NDS_ldapsam modes
856 *********************************************************************/
857
858static NTSTATUS pdb_init_NDS_ldapsam_common(struct pdb_methods **pdb_method, const char *location)
859{
860 struct ldapsam_privates *ldap_state =
861 (struct ldapsam_privates *)((*pdb_method)->private_data);
862
863 /* Mark this as eDirectory ldap */
864 ldap_state->is_nds_ldap = True;
865
866 /* Add pdb_nds specific method for updating login attempts. */
867 (*pdb_method)->update_login_attempts = pdb_nds_update_login_attempts;
868
869 /* Save location for use in pdb_nds_update_login_attempts */
870 ldap_state->location = SMB_STRDUP(location);
871
872 return NT_STATUS_OK;
873}
874
875/**********************************************************************
876 Initialise the 'nds' normal mode for pdb_ldap
877 *********************************************************************/
878
879static NTSTATUS pdb_init_NDS_ldapsam(struct pdb_methods **pdb_method, const char *location)
880{
881 NTSTATUS nt_status = pdb_ldapsam_init_common(pdb_method, location);
882
883 (*pdb_method)->name = "NDS_ldapsam";
884
885 pdb_init_NDS_ldapsam_common(pdb_method, location);
886
887 return nt_status;
888}
889
890NTSTATUS pdb_nds_init(void)
891{
892 NTSTATUS nt_status;
893 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "NDS_ldapsam", pdb_init_NDS_ldapsam)))
894 return nt_status;
895
896 return NT_STATUS_OK;
897}
Note: See TracBrowser for help on using the repository browser.