auth/credentials: don't ignore "client use kerberos" and --use-kerberos for machine...
[Samba.git] / source3 / passdb / pdb_nds.c
blobfc0d19b06f1fdf6ad439feca1eaedd2b801f1cc6
1 /*
2 Unix SMB/CIFS Implementation.
3 NDS LDAP helper functions for SAMBA
4 Copyright (C) Vince Brimhall 2004-2005
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.
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.
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/>.
21 #include "includes.h"
22 #include "passdb.h"
24 #include <lber.h>
25 #include <ldap.h>
27 #include "smbldap.h"
28 #include "passdb/pdb_ldap.h"
29 #include "passdb/pdb_nds.h"
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"
38 #define NMAS_LDAP_EXT_VERSION 1
40 /**********************************************************************
41 Take the request BER value and input data items and BER encodes the
42 data into the BER value
43 **********************************************************************/
45 static int berEncodePasswordData(
46 struct berval **requestBV,
47 const char *objectDN,
48 const char *password,
49 const char *password2)
51 int err = 0, rc=0;
52 BerElement *requestBer = NULL;
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;
62 /* Convert objectDN and tag strings from Unicode to UTF-8 */
63 utf8ObjSize = strlen(objectDN)+1;
64 utf8ObjPtr = objectDN;
66 if (password != NULL)
68 utf8PwdSize = strlen(password)+1;
69 utf8PwdPtr = password;
72 if (password2 != NULL)
74 utf8Pwd2Size = strlen(password2)+1;
75 utf8Pwd2Ptr = password2;
78 /* Allocate a BerElement for the request parameters. */
79 if((requestBer = ber_alloc()) == NULL)
81 err = LDAP_ENCODING_ERROR;
82 goto Cleanup;
85 if (password != NULL && password2 != NULL)
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);
90 else if (password != NULL)
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);
95 else
97 /* BER encode the NMAS Version and the objectDN */
98 rc = ber_printf(requestBer, "{io}", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize);
101 if (rc < 0)
103 err = LDAP_ENCODING_ERROR;
104 goto Cleanup;
106 else
108 err = 0;
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)
114 err = LDAP_ENCODING_ERROR;
115 goto Cleanup;
118 Cleanup:
120 if(requestBer)
122 ber_free(requestBer, 1);
125 return err;
128 /**********************************************************************
129 Take the request BER value and input data items and BER encodes the
130 data into the BER value
131 **********************************************************************/
133 static 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)
142 int err = 0;
143 BerElement *requestBer = NULL;
145 unsigned int i;
146 unsigned int elemCnt = methodIDLen / sizeof(unsigned int);
148 char *utf8ObjPtr=NULL;
149 int utf8ObjSize = 0;
151 char *utf8TagPtr = NULL;
152 int utf8TagSize = 0;
154 utf8ObjPtr = objectDN;
155 utf8ObjSize = strlen(utf8ObjPtr)+1;
157 utf8TagPtr = tag;
158 utf8TagSize = strlen(utf8TagPtr)+1;
160 /* Allocate a BerElement for the request parameters. */
161 if((requestBer = ber_alloc()) == NULL)
163 err = LDAP_ENCODING_ERROR;
164 goto Cleanup;
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;
170 /* BER encode the MethodID Length and value */
171 if (!err)
173 err = (ber_printf(requestBer, "{i{", methodIDLen) < 0) ? LDAP_ENCODING_ERROR : 0;
176 for (i = 0; !err && i < elemCnt; i++)
178 err = (ber_printf(requestBer, "i", methodID[i]) < 0) ? LDAP_ENCODING_ERROR : 0;
181 if (!err)
183 err = (ber_printf(requestBer, "}}", 0) < 0) ? LDAP_ENCODING_ERROR : 0;
186 if (!err) {
187 if (putData) {
188 /* BER Encode the tag and data */
189 err = (ber_printf(requestBer, "oio}", utf8TagPtr,
190 utf8TagSize, putDataLen, putData,
191 putDataLen) < 0)
192 ? LDAP_ENCODING_ERROR : 0;
193 } else {
194 /* BER Encode the tag */
195 err = (ber_printf(requestBer, "o}", utf8TagPtr,
196 utf8TagSize) < 0)
197 ? LDAP_ENCODING_ERROR : 0;
201 if (err)
203 goto Cleanup;
206 /* Convert the BER we just built to a berval that we'll send with the extended request. */
207 if(ber_flatten(requestBer, requestBV) == LBER_ERROR)
209 err = LDAP_ENCODING_ERROR;
210 goto Cleanup;
213 Cleanup:
215 if(requestBer)
217 ber_free(requestBer, 1);
220 return err;
223 /**********************************************************************
224 Takes the reply BER Value and decodes the NMAS server version and
225 return code and if a non null retData buffer was supplied, tries to
226 decode the return data and length
227 **********************************************************************/
229 static int berDecodeLoginData(
230 struct berval *replyBV,
231 int *serverVersion,
232 size_t *retDataLen,
233 void *retData )
235 int err = 0;
236 BerElement *replyBer = NULL;
237 char *retOctStr = NULL;
238 size_t retOctStrLen = 0;
240 if((replyBer = ber_init(replyBV)) == NULL)
242 err = LDAP_OPERATIONS_ERROR;
243 goto Cleanup;
246 if(retData)
248 retOctStrLen = *retDataLen + 1;
249 retOctStr = SMB_MALLOC_ARRAY(char, retOctStrLen);
250 if(!retOctStr)
252 err = LDAP_OPERATIONS_ERROR;
253 goto Cleanup;
256 if(ber_scanf(replyBer, "{iis}", serverVersion, &err, retOctStr, &retOctStrLen) != -1)
258 if (*retDataLen >= retOctStrLen)
260 memcpy(retData, retOctStr, retOctStrLen);
262 else if (!err)
264 err = LDAP_NO_MEMORY;
267 *retDataLen = retOctStrLen;
269 else if (!err)
271 err = LDAP_DECODING_ERROR;
274 else
276 if(ber_scanf(replyBer, "{ii}", serverVersion, &err) == -1)
278 if (!err)
280 err = LDAP_DECODING_ERROR;
285 Cleanup:
287 if(replyBer)
289 ber_free(replyBer, 1);
292 if (retOctStr != NULL)
294 memset(retOctStr, 0, retOctStrLen);
295 free(retOctStr);
298 return err;
301 /**********************************************************************
302 Retrieves data in the login configuration of the specified object
303 that is tagged with the specified methodID and tag.
304 **********************************************************************/
306 static int getLoginConfig(
307 LDAP *ld,
308 char *objectDN,
309 unsigned int methodIDLen,
310 unsigned int *methodID,
311 char *tag,
312 size_t *dataLen,
313 void *data )
315 int err = 0;
316 struct berval *requestBV = NULL;
317 char *replyOID = NULL;
318 struct berval *replyBV = NULL;
319 int serverVersion = 0;
321 /* Validate unicode parameters. */
322 if((strlen(objectDN) == 0) || ld == NULL)
324 return LDAP_NO_SUCH_ATTRIBUTE;
327 err = berEncodeLoginData(&requestBV, objectDN, methodIDLen, methodID, tag, 0, NULL);
328 if(err)
330 goto Cleanup;
333 /* Call the ldap_extended_operation (synchronously) */
334 if((err = ldap_extended_operation_s(ld, NMASLDAP_GET_LOGIN_CONFIG_REQUEST,
335 requestBV, NULL, NULL, &replyOID, &replyBV)))
337 goto Cleanup;
340 /* Make sure there is a return OID */
341 if(!replyOID)
343 err = LDAP_NOT_SUPPORTED;
344 goto Cleanup;
347 /* Is this what we were expecting to get back. */
348 if(strcmp(replyOID, NMASLDAP_GET_LOGIN_CONFIG_RESPONSE))
350 err = LDAP_NOT_SUPPORTED;
351 goto Cleanup;
354 /* Do we have a good returned berval? */
355 if(!replyBV)
357 /* No; returned berval means we experienced a rather drastic error. */
358 /* Return operations error. */
359 err = LDAP_OPERATIONS_ERROR;
360 goto Cleanup;
363 err = berDecodeLoginData(replyBV, &serverVersion, dataLen, data);
365 if(serverVersion != NMAS_LDAP_EXT_VERSION)
367 err = LDAP_OPERATIONS_ERROR;
368 goto Cleanup;
371 Cleanup:
373 if(replyBV)
375 ber_bvfree(replyBV);
378 /* Free the return OID string if one was returned. */
379 if(replyOID)
381 ldap_memfree(replyOID);
384 /* Free memory allocated while building the request ber and berval. */
385 if(requestBV)
387 ber_bvfree(requestBV);
390 /* Return the appropriate error/success code. */
391 return err;
394 /**********************************************************************
395 Attempts to get the Simple Password
396 **********************************************************************/
398 static int nmasldap_get_simple_pwd(
399 LDAP *ld,
400 char *objectDN,
401 size_t pwdLen,
402 char *pwd )
404 int err = 0;
405 unsigned int methodID = 0;
406 unsigned int methodIDLen = sizeof(methodID);
407 char tag[] = {'P','A','S','S','W','O','R','D',' ','H','A','S','H',0};
408 char *pwdBuf=NULL;
409 size_t pwdBufLen, bufferLen;
411 bufferLen = pwdBufLen = pwdLen+2;
412 pwdBuf = SMB_MALLOC_ARRAY(char, pwdBufLen); /* digest and null */
413 if(pwdBuf == NULL)
415 return LDAP_NO_MEMORY;
418 err = getLoginConfig(ld, objectDN, methodIDLen, &methodID, tag, &pwdBufLen, pwdBuf);
419 if (err == 0)
421 if (pwdBufLen !=0)
423 pwdBuf[pwdBufLen] = 0; /* null terminate */
425 switch (pwdBuf[0])
427 case 1: /* cleartext password */
428 break;
429 case 2: /* SHA1 HASH */
430 case 3: /* MD5_ID */
431 case 4: /* UNIXCrypt_ID */
432 case 8: /* SSHA_ID */
433 default: /* Unknown digest */
434 err = LDAP_INAPPROPRIATE_AUTH; /* only return clear text */
435 break;
438 if (!err)
440 if (pwdLen >= pwdBufLen-1)
442 memcpy(pwd, &pwdBuf[1], pwdBufLen-1); /* skip digest tag and include null */
444 else
446 err = LDAP_NO_MEMORY;
452 if (pwdBuf != NULL)
454 memset(pwdBuf, 0, bufferLen);
455 free(pwdBuf);
458 return err;
462 /**********************************************************************
463 Attempts to set the Universal Password
464 **********************************************************************/
466 static int nmasldap_set_password(
467 LDAP *ld,
468 const char *objectDN,
469 const char *pwd )
471 int err = 0;
473 struct berval *requestBV = NULL;
474 char *replyOID = NULL;
475 struct berval *replyBV = NULL;
476 int serverVersion;
478 /* Validate char parameters. */
479 if(objectDN == NULL || (strlen(objectDN) == 0) || pwd == NULL || ld == NULL)
481 return LDAP_NO_SUCH_ATTRIBUTE;
484 err = berEncodePasswordData(&requestBV, objectDN, pwd, NULL);
485 if(err)
487 goto Cleanup;
490 /* Call the ldap_extended_operation (synchronously) */
491 if((err = ldap_extended_operation_s(ld, NMASLDAP_SET_PASSWORD_REQUEST, requestBV, NULL, NULL, &replyOID, &replyBV)))
493 goto Cleanup;
496 /* Make sure there is a return OID */
497 if(!replyOID)
499 err = LDAP_NOT_SUPPORTED;
500 goto Cleanup;
503 /* Is this what we were expecting to get back. */
504 if(strcmp(replyOID, NMASLDAP_SET_PASSWORD_RESPONSE))
506 err = LDAP_NOT_SUPPORTED;
507 goto Cleanup;
510 /* Do we have a good returned berval? */
511 if(!replyBV)
513 /* No; returned berval means we experienced a rather drastic error. */
514 /* Return operations error. */
515 err = LDAP_OPERATIONS_ERROR;
516 goto Cleanup;
519 err = berDecodeLoginData(replyBV, &serverVersion, NULL, NULL);
521 if(serverVersion != NMAS_LDAP_EXT_VERSION)
523 err = LDAP_OPERATIONS_ERROR;
524 goto Cleanup;
527 Cleanup:
529 if(replyBV)
531 ber_bvfree(replyBV);
534 /* Free the return OID string if one was returned. */
535 if(replyOID)
537 ldap_memfree(replyOID);
540 /* Free memory allocated while building the request ber and berval. */
541 if(requestBV)
543 ber_bvfree(requestBV);
546 /* Return the appropriate error/success code. */
547 return err;
550 /**********************************************************************
551 Attempts to get the Universal Password
552 **********************************************************************/
554 static int nmasldap_get_password(
555 LDAP *ld,
556 char *objectDN,
557 size_t *pwdSize, /* in bytes */
558 unsigned char *pwd )
560 int err = 0;
562 struct berval *requestBV = NULL;
563 char *replyOID = NULL;
564 struct berval *replyBV = NULL;
565 int serverVersion;
566 char *pwdBuf;
567 size_t pwdBufLen, bufferLen;
569 /* Validate char parameters. */
570 if(objectDN == NULL || (strlen(objectDN) == 0) || pwdSize == NULL || ld == NULL)
572 return LDAP_NO_SUCH_ATTRIBUTE;
575 bufferLen = pwdBufLen = *pwdSize;
576 pwdBuf = SMB_MALLOC_ARRAY(char, pwdBufLen+2);
577 if(pwdBuf == NULL)
579 return LDAP_NO_MEMORY;
582 err = berEncodePasswordData(&requestBV, objectDN, NULL, NULL);
583 if(err)
585 goto Cleanup;
588 /* Call the ldap_extended_operation (synchronously) */
589 if((err = ldap_extended_operation_s(ld, NMASLDAP_GET_PASSWORD_REQUEST, requestBV, NULL, NULL, &replyOID, &replyBV)))
591 goto Cleanup;
594 /* Make sure there is a return OID */
595 if(!replyOID)
597 err = LDAP_NOT_SUPPORTED;
598 goto Cleanup;
601 /* Is this what we were expecting to get back. */
602 if(strcmp(replyOID, NMASLDAP_GET_PASSWORD_RESPONSE))
604 err = LDAP_NOT_SUPPORTED;
605 goto Cleanup;
608 /* Do we have a good returned berval? */
609 if(!replyBV)
611 /* No; returned berval means we experienced a rather drastic error. */
612 /* Return operations error. */
613 err = LDAP_OPERATIONS_ERROR;
614 goto Cleanup;
617 err = berDecodeLoginData(replyBV, &serverVersion, &pwdBufLen, pwdBuf);
619 if(serverVersion != NMAS_LDAP_EXT_VERSION)
621 err = LDAP_OPERATIONS_ERROR;
622 goto Cleanup;
625 if (!err && pwdBufLen != 0)
627 if (*pwdSize >= pwdBufLen+1 && pwd != NULL)
629 memcpy(pwd, pwdBuf, pwdBufLen);
630 pwd[pwdBufLen] = 0; /* add null termination */
632 *pwdSize = pwdBufLen; /* does not include null termination */
635 Cleanup:
637 if(replyBV)
639 ber_bvfree(replyBV);
642 /* Free the return OID string if one was returned. */
643 if(replyOID)
645 ldap_memfree(replyOID);
648 /* Free memory allocated while building the request ber and berval. */
649 if(requestBV)
651 ber_bvfree(requestBV);
654 if (pwdBuf != NULL)
656 memset(pwdBuf, 0, bufferLen);
657 free(pwdBuf);
660 /* Return the appropriate error/success code. */
661 return err;
664 /**********************************************************************
665 Get the user's password from NDS.
666 *********************************************************************/
668 int pdb_nds_get_password(
669 struct smbldap_state *ldap_state,
670 char *object_dn,
671 size_t *pwd_len,
672 char *pwd )
674 LDAP *ld = smbldap_get_ldap(ldap_state);
675 int rc = -1;
677 rc = nmasldap_get_password(ld, object_dn, pwd_len, (unsigned char *)pwd);
678 if (rc == LDAP_SUCCESS) {
679 #ifdef DEBUG_PASSWORD
680 DEBUG(100,("nmasldap_get_password returned %s for %s\n", pwd, object_dn));
681 #endif
682 DEBUG(5, ("NDS Universal Password retrieved for %s\n", object_dn));
683 } else {
684 DEBUG(3, ("NDS Universal Password NOT retrieved for %s\n", object_dn));
687 if (rc != LDAP_SUCCESS) {
688 rc = nmasldap_get_simple_pwd(ld, object_dn, *pwd_len, pwd);
689 if (rc == LDAP_SUCCESS) {
690 #ifdef DEBUG_PASSWORD
691 DEBUG(100,("nmasldap_get_simple_pwd returned %s for %s\n", pwd, object_dn));
692 #endif
693 DEBUG(5, ("NDS Simple Password retrieved for %s\n", object_dn));
694 } else {
695 /* We couldn't get the password */
696 DEBUG(3, ("NDS Simple Password NOT retrieved for %s\n", object_dn));
697 return LDAP_INVALID_CREDENTIALS;
701 /* We got the password */
702 return LDAP_SUCCESS;
705 /**********************************************************************
706 Set the users NDS, Universal and Simple passwords.
707 ********************************************************************/
709 int pdb_nds_set_password(
710 struct smbldap_state *ldap_state,
711 char *object_dn,
712 const char *pwd )
714 LDAP *ld = smbldap_get_ldap(ldap_state);
715 int rc = -1;
716 LDAPMod **tmpmods = NULL;
718 rc = nmasldap_set_password(ld, object_dn, pwd);
719 if (rc == LDAP_SUCCESS) {
720 DEBUG(5,("NDS Universal Password changed for user %s\n", object_dn));
721 } else {
722 char *ld_error = NULL;
723 ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &ld_error);
725 /* This will fail if Universal Password is not enabled for the user's context */
726 DEBUG(3,("NDS Universal Password could not be changed for user %s: %s (%s)\n",
727 object_dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
728 SAFE_FREE(ld_error);
731 /* Set eDirectory Password */
732 smbldap_set_mod(&tmpmods, LDAP_MOD_REPLACE, "userPassword", pwd);
733 rc = smbldap_modify(ldap_state, object_dn, tmpmods);
735 return rc;
738 /**********************************************************************
739 Allow ldap server to update internal login attempt counters by
740 performing a simple bind. If the samba authentication failed attempt
741 the bind with a bogus, randomly generated password to count the
742 failed attempt. If the bind fails even though samba authentication
743 succeeded, this would indicate that the user's account is disabled,
744 time restrictions are in place or some other password policy
745 violation.
746 *********************************************************************/
748 static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
749 struct samu *sam_acct, bool success)
751 struct ldapsam_privates *ldap_state;
753 if ((!methods) || (!sam_acct)) {
754 DEBUG(3,("pdb_nds_update_login_attempts: invalid parameter.\n"));
755 return NT_STATUS_MEMORY_NOT_ALLOCATED;
758 ldap_state = (struct ldapsam_privates *)methods->private_data;
760 if (ldap_state) {
761 /* Attempt simple bind with user credentials to update eDirectory
762 password policy */
763 int rc = 0;
764 char *dn;
765 LDAPMessage *result = NULL;
766 LDAPMessage *entry = NULL;
767 const char **attr_list;
768 size_t pwd_len;
769 char clear_text_pw[512];
770 LDAP *ld = NULL;
771 const char *username = pdb_get_username(sam_acct);
772 bool got_clear_text_pw = False;
774 DEBUG(5,("pdb_nds_update_login_attempts: %s login for %s\n",
775 success ? "Successful" : "Failed", username));
777 result = (LDAPMessage *)pdb_get_backend_private_data(sam_acct, methods);
778 if (!result) {
779 attr_list = get_userattr_list(NULL,
780 ldap_state->schema_ver);
781 rc = ldapsam_search_suffix_by_name(ldap_state, username, &result, attr_list );
782 TALLOC_FREE( attr_list );
783 if (rc != LDAP_SUCCESS) {
784 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
786 pdb_set_backend_private_data(sam_acct, result, NULL,
787 methods, PDB_CHANGED);
788 smbldap_talloc_autofree_ldapmsg(sam_acct, result);
791 if (ldap_count_entries(
792 smbldap_get_ldap(ldap_state->smbldap_state),
793 result) == 0) {
794 DEBUG(0, ("pdb_nds_update_login_attempts: No user to modify!\n"));
795 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
798 entry = ldap_first_entry(
799 smbldap_get_ldap(ldap_state->smbldap_state), result);
800 dn = smbldap_talloc_dn(talloc_tos(),
801 smbldap_get_ldap(
802 ldap_state->smbldap_state),
803 entry);
804 if (!dn) {
805 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
808 DEBUG(3, ("pdb_nds_update_login_attempts: username %s found dn '%s'\n", username, dn));
810 pwd_len = sizeof(clear_text_pw);
811 if (success == True) {
812 if (pdb_nds_get_password(ldap_state->smbldap_state, dn, &pwd_len, clear_text_pw) == LDAP_SUCCESS) {
813 /* Got clear text password. Use simple ldap bind */
814 got_clear_text_pw = True;
816 } else {
817 /* This is a long term key */
818 generate_secret_buffer((unsigned char *)clear_text_pw, 24);
819 clear_text_pw[24] = '\0';
820 DEBUG(5,("pdb_nds_update_login_attempts: using random password %s\n", clear_text_pw));
823 if((success != True) || (got_clear_text_pw == True)) {
825 rc = smbldap_setup_full_conn(&ld, ldap_state->location);
826 if (rc) {
827 TALLOC_FREE(dn);
828 return NT_STATUS_INVALID_CONNECTION;
831 /* Attempt simple bind with real or bogus password */
832 rc = ldap_simple_bind_s(ld, dn, clear_text_pw);
833 ldap_unbind(ld);
834 if (rc == LDAP_SUCCESS) {
835 DEBUG(5,("pdb_nds_update_login_attempts: ldap_simple_bind_s Successful for %s\n", username));
836 } else {
837 NTSTATUS nt_status = NT_STATUS_ACCOUNT_RESTRICTION;
838 DEBUG(5,("pdb_nds_update_login_attempts: ldap_simple_bind_s Failed for %s\n", username));
839 switch(rc) {
840 case LDAP_INVALID_CREDENTIALS:
841 nt_status = NT_STATUS_WRONG_PASSWORD;
842 break;
843 case LDAP_UNWILLING_TO_PERFORM:
844 /* eDir returns this if the account was disabled. */
845 /* The problem is we don't know if the given
846 password was correct for this account or
847 not. We have to return more info than we
848 should and tell the client NT_STATUS_ACCOUNT_DISABLED
849 so they don't think the password was bad. JRA. */
850 nt_status = NT_STATUS_ACCOUNT_DISABLED;
851 break;
852 default:
853 break;
855 return nt_status;
858 TALLOC_FREE(dn);
861 return NT_STATUS_OK;
864 /**********************************************************************
865 Initialise the parts of the pdb_methods structure that are common
866 to NDS_ldapsam modes
867 *********************************************************************/
869 static NTSTATUS pdb_init_NDS_ldapsam_common(struct pdb_methods **pdb_method, const char *location)
871 struct ldapsam_privates *ldap_state =
872 (struct ldapsam_privates *)((*pdb_method)->private_data);
874 /* Mark this as eDirectory ldap */
875 ldap_state->is_nds_ldap = True;
877 /* Add pdb_nds specific method for updating login attempts. */
878 (*pdb_method)->update_login_attempts = pdb_nds_update_login_attempts;
880 /* Save location for use in pdb_nds_update_login_attempts */
881 ldap_state->location = SMB_STRDUP(location);
883 return NT_STATUS_OK;
886 /**********************************************************************
887 Initialise the 'nds' normal mode for pdb_ldap
888 *********************************************************************/
890 static NTSTATUS pdb_init_NDS_ldapsam(struct pdb_methods **pdb_method, const char *location)
892 NTSTATUS nt_status = pdb_ldapsam_init_common(pdb_method, location);
894 (*pdb_method)->name = "NDS_ldapsam";
896 pdb_init_NDS_ldapsam_common(pdb_method, location);
898 return nt_status;
901 NTSTATUS pdb_nds_init(TALLOC_CTX *ctx)
903 NTSTATUS nt_status;
904 if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "NDS_ldapsam", pdb_init_NDS_ldapsam)))
905 return nt_status;
907 return NT_STATUS_OK;