passdb/pdb_nds.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS mplementation.
00003    NDS LDAP helper functions for SAMBA
00004    Copyright (C) Vince Brimhall                 2004-2005
00005     
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015    
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019    
00020 */
00021 
00022 #include "includes.h"
00023 
00024 #include <lber.h>
00025 #include <ldap.h>
00026 #include <wchar.h>
00027 
00028 #include "smbldap.h"
00029 
00030 #define NMASLDAP_GET_LOGIN_CONFIG_REQUEST       "2.16.840.1.113719.1.39.42.100.3"
00031 #define NMASLDAP_GET_LOGIN_CONFIG_RESPONSE      "2.16.840.1.113719.1.39.42.100.4"
00032 #define NMASLDAP_SET_PASSWORD_REQUEST           "2.16.840.1.113719.1.39.42.100.11"
00033 #define NMASLDAP_SET_PASSWORD_RESPONSE          "2.16.840.1.113719.1.39.42.100.12"
00034 #define NMASLDAP_GET_PASSWORD_REQUEST           "2.16.840.1.113719.1.39.42.100.13"
00035 #define NMASLDAP_GET_PASSWORD_RESPONSE          "2.16.840.1.113719.1.39.42.100.14"
00036 
00037 #define NMAS_LDAP_EXT_VERSION                           1
00038 
00039 /**********************************************************************
00040  Take the request BER value and input data items and BER encodes the
00041  data into the BER value
00042 **********************************************************************/
00043 
00044 static int berEncodePasswordData(
00045         struct berval **requestBV,
00046         const char    *objectDN,
00047         const char    *password,
00048         const char    *password2)
00049 {
00050         int err = 0, rc=0;
00051         BerElement *requestBer = NULL;
00052 
00053         const char    * utf8ObjPtr = NULL;
00054         int     utf8ObjSize = 0;
00055         const char    * utf8PwdPtr = NULL;
00056         int     utf8PwdSize = 0;
00057         const char    * utf8Pwd2Ptr = NULL;
00058         int     utf8Pwd2Size = 0;
00059 
00060 
00061         /* Convert objectDN and tag strings from Unicode to UTF-8 */
00062         utf8ObjSize = strlen(objectDN)+1;
00063         utf8ObjPtr = objectDN;
00064 
00065         if (password != NULL)
00066         {
00067                 utf8PwdSize = strlen(password)+1;
00068                 utf8PwdPtr = password;
00069         }
00070 
00071         if (password2 != NULL)
00072         {
00073                 utf8Pwd2Size = strlen(password2)+1;
00074                 utf8Pwd2Ptr = password2;
00075         }
00076 
00077         /* Allocate a BerElement for the request parameters. */
00078         if((requestBer = ber_alloc()) == NULL)
00079         {
00080                 err = LDAP_ENCODING_ERROR;
00081                 goto Cleanup;
00082         }
00083 
00084         if (password != NULL && password2 != NULL)
00085         {
00086                 /* BER encode the NMAS Version, the objectDN, and the password */
00087                 rc = ber_printf(requestBer, "{iooo}", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize, utf8PwdPtr, utf8PwdSize, utf8Pwd2Ptr, utf8Pwd2Size);
00088         }
00089         else if (password != NULL)
00090         {
00091                 /* BER encode the NMAS Version, the objectDN, and the password */
00092                 rc = ber_printf(requestBer, "{ioo}", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize, utf8PwdPtr, utf8PwdSize);
00093         }
00094         else
00095         {
00096                 /* BER encode the NMAS Version and the objectDN */
00097                 rc = ber_printf(requestBer, "{io}", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize);
00098         }
00099 
00100         if (rc < 0)
00101         {
00102                 err = LDAP_ENCODING_ERROR;
00103                 goto Cleanup;
00104         }
00105         else
00106         {
00107                 err = 0;
00108         }
00109 
00110         /* Convert the BER we just built to a berval that we'll send with the extended request. */
00111         if(ber_flatten(requestBer, requestBV) == LBER_ERROR)
00112         {
00113                 err = LDAP_ENCODING_ERROR;
00114                 goto Cleanup;
00115         }
00116 
00117 Cleanup:
00118 
00119         if(requestBer)
00120         {
00121                 ber_free(requestBer, 1);
00122         }
00123 
00124         return err;
00125 }
00126 
00127 /**********************************************************************
00128  Take the request BER value and input data items and BER encodes the
00129  data into the BER value
00130 **********************************************************************/
00131 
00132 static int berEncodeLoginData(
00133         struct berval **requestBV,
00134         char     *objectDN,
00135         unsigned int  methodIDLen,
00136         unsigned int *methodID,
00137         char     *tag,
00138         size_t   putDataLen,
00139         void     *putData)
00140 {
00141         int err = 0;
00142         BerElement *requestBer = NULL;
00143 
00144         unsigned int i;
00145         unsigned int elemCnt = methodIDLen / sizeof(unsigned int);
00146 
00147         char    *utf8ObjPtr=NULL;
00148         int     utf8ObjSize = 0;
00149 
00150         char    *utf8TagPtr = NULL;
00151         int     utf8TagSize = 0;
00152 
00153         utf8ObjPtr = objectDN;
00154         utf8ObjSize = strlen(utf8ObjPtr)+1;
00155 
00156         utf8TagPtr = tag;
00157         utf8TagSize = strlen(utf8TagPtr)+1;
00158 
00159         /* Allocate a BerElement for the request parameters. */
00160         if((requestBer = ber_alloc()) == NULL)
00161         {
00162                 err = LDAP_ENCODING_ERROR;
00163                 goto Cleanup;
00164         }
00165 
00166         /* BER encode the NMAS Version and the objectDN */
00167         err = (ber_printf(requestBer, "{io", NMAS_LDAP_EXT_VERSION, utf8ObjPtr, utf8ObjSize) < 0) ? LDAP_ENCODING_ERROR : 0;
00168 
00169         /* BER encode the MethodID Length and value */
00170         if (!err)
00171         {
00172                 err = (ber_printf(requestBer, "{i{", methodIDLen) < 0) ? LDAP_ENCODING_ERROR : 0;
00173         }
00174 
00175         for (i = 0; !err && i < elemCnt; i++)
00176         {
00177                 err = (ber_printf(requestBer, "i", methodID[i]) < 0) ? LDAP_ENCODING_ERROR : 0;
00178         }
00179 
00180         if (!err)
00181         {
00182                 err = (ber_printf(requestBer, "}}", 0) < 0) ? LDAP_ENCODING_ERROR : 0;
00183         }
00184 
00185         if(putData)
00186         {
00187                 /* BER Encode the the tag and data */
00188                 err = (ber_printf(requestBer, "oio}", utf8TagPtr, utf8TagSize, putDataLen, putData, putDataLen) < 0) ? LDAP_ENCODING_ERROR : 0;
00189         }
00190         else
00191         {
00192                 /* BER Encode the the tag */
00193                 err = (ber_printf(requestBer, "o}", utf8TagPtr, utf8TagSize) < 0) ? LDAP_ENCODING_ERROR : 0;
00194         }
00195 
00196         if (err)
00197         {
00198                 goto Cleanup;
00199         }
00200 
00201         /* Convert the BER we just built to a berval that we'll send with the extended request. */
00202         if(ber_flatten(requestBer, requestBV) == LBER_ERROR)
00203         {
00204                 err = LDAP_ENCODING_ERROR;
00205                 goto Cleanup;
00206         }
00207 
00208 Cleanup:
00209 
00210         if(requestBer)
00211         {
00212                 ber_free(requestBer, 1);
00213         }
00214 
00215         return err;
00216 }
00217 
00218 /**********************************************************************
00219  Takes the reply BER Value and decodes the NMAS server version and
00220  return code and if a non null retData buffer was supplied, tries to
00221  decode the the return data and length
00222 **********************************************************************/
00223 
00224 static int berDecodeLoginData(
00225         struct berval *replyBV,
00226         int      *serverVersion,
00227         size_t   *retDataLen,
00228         void     *retData )
00229 {
00230         int err = 0;
00231         BerElement *replyBer = NULL;
00232         char    *retOctStr = NULL;
00233         size_t  retOctStrLen = 0;
00234 
00235         if((replyBer = ber_init(replyBV)) == NULL)
00236         {
00237                 err = LDAP_OPERATIONS_ERROR;
00238                 goto Cleanup;
00239         }
00240 
00241         if(retData)
00242         {
00243                 retOctStrLen = *retDataLen + 1;
00244                 retOctStr = SMB_MALLOC_ARRAY(char, retOctStrLen);
00245                 if(!retOctStr)
00246                 {
00247                         err = LDAP_OPERATIONS_ERROR;
00248                         goto Cleanup;
00249                 }
00250         
00251                 if(ber_scanf(replyBer, "{iis}", serverVersion, &err, retOctStr, &retOctStrLen) != -1)
00252                 {
00253                         if (*retDataLen >= retOctStrLen)
00254                         {
00255                                 memcpy(retData, retOctStr, retOctStrLen);
00256                         }
00257                         else if (!err)
00258                         {       
00259                                 err = LDAP_NO_MEMORY;
00260                         }
00261 
00262                         *retDataLen = retOctStrLen;
00263                 }
00264                 else if (!err)
00265                 {
00266                         err = LDAP_DECODING_ERROR;
00267                 }
00268         }
00269         else
00270         {
00271                 if(ber_scanf(replyBer, "{ii}", serverVersion, &err) == -1)
00272                 {
00273                         if (!err)
00274                         {
00275                                 err = LDAP_DECODING_ERROR;
00276                         }
00277                 }
00278         }
00279 
00280 Cleanup:
00281 
00282         if(replyBer)
00283         {
00284                 ber_free(replyBer, 1);
00285         }
00286 
00287         if (retOctStr != NULL)
00288         {
00289                 memset(retOctStr, 0, retOctStrLen);
00290                 free(retOctStr);
00291         }
00292 
00293         return err;
00294 }
00295 
00296 /**********************************************************************
00297  Retrieves data in the login configuration of the specified object
00298  that is tagged with the specified methodID and tag.
00299 **********************************************************************/
00300 
00301 static int getLoginConfig(
00302         LDAP     *ld,
00303         char     *objectDN,
00304         unsigned int  methodIDLen,
00305         unsigned int *methodID,
00306         char     *tag,
00307         size_t   *dataLen,
00308         void     *data )
00309 {
00310         int     err = 0;
00311         struct  berval *requestBV = NULL;
00312         char    *replyOID = NULL;
00313         struct  berval *replyBV = NULL;
00314         int     serverVersion = 0;
00315 
00316         /* Validate unicode parameters. */
00317         if((strlen(objectDN) == 0) || ld == NULL)
00318         {
00319                 return LDAP_NO_SUCH_ATTRIBUTE;
00320         }
00321 
00322         err = berEncodeLoginData(&requestBV, objectDN, methodIDLen, methodID, tag, 0, NULL);
00323         if(err)
00324         {
00325                 goto Cleanup;
00326         }
00327 
00328         /* Call the ldap_extended_operation (synchronously) */
00329         if((err = ldap_extended_operation_s(ld, NMASLDAP_GET_LOGIN_CONFIG_REQUEST,
00330                                         requestBV, NULL, NULL, &replyOID, &replyBV)))
00331         {
00332                 goto Cleanup;
00333         }
00334 
00335         /* Make sure there is a return OID */
00336         if(!replyOID)
00337         {
00338                 err = LDAP_NOT_SUPPORTED;
00339                 goto Cleanup;
00340         }
00341 
00342         /* Is this what we were expecting to get back. */
00343         if(strcmp(replyOID, NMASLDAP_GET_LOGIN_CONFIG_RESPONSE))
00344         {
00345                 err = LDAP_NOT_SUPPORTED;
00346                 goto Cleanup;
00347         }
00348 
00349         /* Do we have a good returned berval? */
00350         if(!replyBV)
00351         {
00352                 /* No; returned berval means we experienced a rather drastic error. */
00353                 /* Return operations error. */
00354                 err = LDAP_OPERATIONS_ERROR;
00355                 goto Cleanup;
00356         }
00357 
00358         err = berDecodeLoginData(replyBV, &serverVersion, dataLen, data);
00359 
00360         if(serverVersion != NMAS_LDAP_EXT_VERSION)
00361         {
00362                 err = LDAP_OPERATIONS_ERROR;
00363                 goto Cleanup;
00364         }
00365 
00366 Cleanup:
00367 
00368         if(replyBV)
00369         {
00370                 ber_bvfree(replyBV);
00371         }
00372 
00373         /* Free the return OID string if one was returned. */
00374         if(replyOID)
00375         {
00376                 ldap_memfree(replyOID);
00377         }
00378 
00379         /* Free memory allocated while building the request ber and berval. */
00380         if(requestBV)
00381         {
00382                 ber_bvfree(requestBV);
00383         }
00384 
00385         /* Return the appropriate error/success code. */
00386         return err;
00387 }
00388 
00389 /**********************************************************************
00390  Attempts to get the Simple Password
00391 **********************************************************************/
00392 
00393 static int nmasldap_get_simple_pwd(
00394         LDAP     *ld,
00395         char     *objectDN,
00396         size_t   pwdLen,
00397         char     *pwd )
00398 {
00399         int err = 0;
00400         unsigned int methodID = 0;
00401         unsigned int methodIDLen = sizeof(methodID);
00402         char    tag[] = {'P','A','S','S','W','O','R','D',' ','H','A','S','H',0};
00403         char    *pwdBuf=NULL;
00404         size_t  pwdBufLen, bufferLen;
00405 
00406         bufferLen = pwdBufLen = pwdLen+2;
00407         pwdBuf = SMB_MALLOC_ARRAY(char, pwdBufLen); /* digest and null */
00408         if(pwdBuf == NULL)
00409         {
00410                 return LDAP_NO_MEMORY;
00411         }
00412 
00413         err = getLoginConfig(ld, objectDN, methodIDLen, &methodID, tag, &pwdBufLen, pwdBuf);
00414         if (err == 0)
00415         {
00416                 if (pwdBufLen !=0)
00417                 {
00418                         pwdBuf[pwdBufLen] = 0;       /* null terminate */
00419 
00420                         switch (pwdBuf[0])
00421                         {
00422                                 case 1:  /* cleartext password  */
00423                                         break;
00424                                 case 2:  /* SHA1 HASH */
00425                                 case 3:  /* MD5_ID */
00426                                 case 4:  /* UNIXCrypt_ID */
00427                                 case 8:  /* SSHA_ID */
00428                                 default: /* Unknown digest */
00429                                         err = LDAP_INAPPROPRIATE_AUTH;  /* only return clear text */
00430                                         break;
00431                         }
00432 
00433                         if (!err)
00434                         {
00435                                 if (pwdLen >= pwdBufLen-1)
00436                                 {
00437                                         memcpy(pwd, &pwdBuf[1], pwdBufLen-1);  /* skip digest tag and include null */
00438                                 }
00439                                 else
00440                                 {
00441                                         err = LDAP_NO_MEMORY;
00442                                 }
00443                         }
00444                 }
00445         }
00446 
00447         if (pwdBuf != NULL)
00448         {
00449                 memset(pwdBuf, 0, bufferLen);
00450                 free(pwdBuf);
00451         }
00452 
00453         return err;
00454 }
00455 
00456 
00457 /**********************************************************************
00458  Attempts to set the Universal Password
00459 **********************************************************************/
00460 
00461 static int nmasldap_set_password(
00462         LDAP     *ld,
00463         const char     *objectDN,
00464         const char     *pwd )
00465 {
00466         int err = 0;
00467 
00468         struct berval *requestBV = NULL;
00469         char *replyOID = NULL;
00470         struct berval *replyBV = NULL;
00471         int serverVersion;
00472 
00473         /* Validate char parameters. */
00474         if(objectDN == NULL || (strlen(objectDN) == 0) || pwd == NULL || ld == NULL)
00475         {
00476                 return LDAP_NO_SUCH_ATTRIBUTE;
00477         }
00478 
00479         err = berEncodePasswordData(&requestBV, objectDN, pwd, NULL);
00480         if(err)
00481         {
00482                 goto Cleanup;
00483         }
00484 
00485         /* Call the ldap_extended_operation (synchronously) */
00486         if((err = ldap_extended_operation_s(ld, NMASLDAP_SET_PASSWORD_REQUEST, requestBV, NULL, NULL, &replyOID, &replyBV)))
00487         {
00488                 goto Cleanup;
00489         }
00490 
00491         /* Make sure there is a return OID */
00492         if(!replyOID)
00493         {
00494                 err = LDAP_NOT_SUPPORTED;
00495                 goto Cleanup;
00496         }
00497 
00498         /* Is this what we were expecting to get back. */
00499         if(strcmp(replyOID, NMASLDAP_SET_PASSWORD_RESPONSE))
00500         {
00501                 err = LDAP_NOT_SUPPORTED;
00502                 goto Cleanup;
00503         }
00504 
00505         /* Do we have a good returned berval? */
00506         if(!replyBV)
00507         {
00508                 /* No; returned berval means we experienced a rather drastic error. */
00509                 /* Return operations error. */
00510                 err = LDAP_OPERATIONS_ERROR;
00511                 goto Cleanup;
00512         }
00513 
00514         err = berDecodeLoginData(replyBV, &serverVersion, NULL, NULL);
00515 
00516         if(serverVersion != NMAS_LDAP_EXT_VERSION)
00517         {
00518                 err = LDAP_OPERATIONS_ERROR;
00519                 goto Cleanup;
00520         }
00521 
00522 Cleanup:
00523 
00524         if(replyBV)
00525         {
00526                 ber_bvfree(replyBV);
00527         }
00528 
00529         /* Free the return OID string if one was returned. */
00530         if(replyOID)
00531         {
00532                 ldap_memfree(replyOID);
00533         }
00534 
00535         /* Free memory allocated while building the request ber and berval. */
00536         if(requestBV)
00537         {
00538                 ber_bvfree(requestBV);
00539         }
00540 
00541         /* Return the appropriate error/success code. */
00542         return err;
00543 }
00544 
00545 /**********************************************************************
00546  Attempts to get the Universal Password
00547 **********************************************************************/
00548 
00549 static int nmasldap_get_password(
00550         LDAP     *ld,
00551         char     *objectDN,
00552         size_t   *pwdSize,      /* in bytes */
00553         unsigned char     *pwd )
00554 {
00555         int err = 0;
00556 
00557         struct berval *requestBV = NULL;
00558         char *replyOID = NULL;
00559         struct berval *replyBV = NULL;
00560         int serverVersion;
00561         char *pwdBuf;
00562         size_t pwdBufLen, bufferLen;
00563 
00564         /* Validate char parameters. */
00565         if(objectDN == NULL || (strlen(objectDN) == 0) || pwdSize == NULL || ld == NULL)
00566         {
00567                 return LDAP_NO_SUCH_ATTRIBUTE;
00568         }
00569 
00570         bufferLen = pwdBufLen = *pwdSize;
00571         pwdBuf = SMB_MALLOC_ARRAY(char, pwdBufLen+2);
00572         if(pwdBuf == NULL)
00573         {
00574                 return LDAP_NO_MEMORY;
00575         }
00576 
00577         err = berEncodePasswordData(&requestBV, objectDN, NULL, NULL);
00578         if(err)
00579         {
00580                 goto Cleanup;
00581         }
00582 
00583         /* Call the ldap_extended_operation (synchronously) */
00584         if((err = ldap_extended_operation_s(ld, NMASLDAP_GET_PASSWORD_REQUEST, requestBV, NULL, NULL, &replyOID, &replyBV)))
00585         {
00586                 goto Cleanup;
00587         }
00588 
00589         /* Make sure there is a return OID */
00590         if(!replyOID)
00591         {
00592                 err = LDAP_NOT_SUPPORTED;
00593                 goto Cleanup;
00594         }
00595 
00596         /* Is this what we were expecting to get back. */
00597         if(strcmp(replyOID, NMASLDAP_GET_PASSWORD_RESPONSE))
00598         {
00599                 err = LDAP_NOT_SUPPORTED;
00600                 goto Cleanup;
00601         }
00602 
00603         /* Do we have a good returned berval? */
00604         if(!replyBV)
00605         {
00606                 /* No; returned berval means we experienced a rather drastic error. */
00607                 /* Return operations error. */
00608                 err = LDAP_OPERATIONS_ERROR;
00609                 goto Cleanup;
00610         }
00611 
00612         err = berDecodeLoginData(replyBV, &serverVersion, &pwdBufLen, pwdBuf);
00613 
00614         if(serverVersion != NMAS_LDAP_EXT_VERSION)
00615         {
00616                 err = LDAP_OPERATIONS_ERROR;
00617                 goto Cleanup;
00618         }
00619 
00620         if (!err && pwdBufLen != 0)
00621         {
00622                 if (*pwdSize >= pwdBufLen+1 && pwd != NULL)
00623                 {
00624                         memcpy(pwd, pwdBuf, pwdBufLen);
00625                         pwd[pwdBufLen] = 0; /* add null termination */
00626                 }
00627                 *pwdSize = pwdBufLen; /* does not include null termination */
00628         }
00629 
00630 Cleanup:
00631 
00632         if(replyBV)
00633         {
00634                 ber_bvfree(replyBV);
00635         }
00636 
00637         /* Free the return OID string if one was returned. */
00638         if(replyOID)
00639         {
00640                 ldap_memfree(replyOID);
00641         }
00642 
00643         /* Free memory allocated while building the request ber and berval. */
00644         if(requestBV)
00645         {
00646                 ber_bvfree(requestBV);
00647         }
00648 
00649         if (pwdBuf != NULL)
00650         {
00651                 memset(pwdBuf, 0, bufferLen);
00652                 free(pwdBuf);
00653         }
00654 
00655         /* Return the appropriate error/success code. */
00656         return err;
00657 }
00658 
00659 /**********************************************************************
00660  Get the user's password from NDS.
00661  *********************************************************************/
00662 
00663 int pdb_nds_get_password(
00664         struct smbldap_state *ldap_state,
00665         char *object_dn,
00666         size_t *pwd_len,
00667         char *pwd )
00668 {
00669         LDAP *ld = ldap_state->ldap_struct;
00670         int rc = -1;
00671 
00672         rc = nmasldap_get_password(ld, object_dn, pwd_len, (unsigned char *)pwd);
00673         if (rc == LDAP_SUCCESS) {
00674 #ifdef DEBUG_PASSWORD
00675                 DEBUG(100,("nmasldap_get_password returned %s for %s\n", pwd, object_dn));
00676 #endif    
00677                 DEBUG(5, ("NDS Universal Password retrieved for %s\n", object_dn));
00678         } else {
00679                 DEBUG(3, ("NDS Universal Password NOT retrieved for %s\n", object_dn));
00680         }
00681 
00682         if (rc != LDAP_SUCCESS) {
00683                 rc = nmasldap_get_simple_pwd(ld, object_dn, *pwd_len, pwd);
00684                 if (rc == LDAP_SUCCESS) {
00685 #ifdef DEBUG_PASSWORD
00686                         DEBUG(100,("nmasldap_get_simple_pwd returned %s for %s\n", pwd, object_dn));
00687 #endif    
00688                         DEBUG(5, ("NDS Simple Password retrieved for %s\n", object_dn));
00689                 } else {
00690                         /* We couldn't get the password */
00691                         DEBUG(3, ("NDS Simple Password NOT retrieved for %s\n", object_dn));
00692                         return LDAP_INVALID_CREDENTIALS;
00693                 }
00694         }
00695 
00696         /* We got the password */
00697         return LDAP_SUCCESS;
00698 }
00699 
00700 /**********************************************************************
00701  Set the users NDS, Universal and Simple passwords.
00702  ********************************************************************/
00703 
00704 int pdb_nds_set_password(
00705         struct smbldap_state *ldap_state,
00706         char *object_dn,
00707         const char *pwd )
00708 {
00709         LDAP *ld = ldap_state->ldap_struct;
00710         int rc = -1;
00711         LDAPMod **tmpmods = NULL;
00712 
00713         rc = nmasldap_set_password(ld, object_dn, pwd);
00714         if (rc == LDAP_SUCCESS) {
00715                 DEBUG(5,("NDS Universal Password changed for user %s\n", object_dn));
00716         } else {
00717                 char *ld_error = NULL;
00718                 ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &ld_error);
00719                 
00720                 /* This will fail if Universal Password is not enabled for the user's context */
00721                 DEBUG(3,("NDS Universal Password could not be changed for user %s: %s (%s)\n",
00722                                  object_dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
00723                 SAFE_FREE(ld_error);
00724         }
00725 
00726         /* Set eDirectory Password */
00727         smbldap_set_mod(&tmpmods, LDAP_MOD_REPLACE, "userPassword", pwd);
00728         rc = smbldap_modify(ldap_state, object_dn, tmpmods);
00729 
00730         return rc;
00731 }
00732 
00733 /**********************************************************************
00734  Allow ldap server to update internal login attempt counters by
00735   performing a simple bind. If the samba authentication failed attempt
00736   the bind with a bogus, randomly generated password to count the
00737   failed attempt. If the bind fails even though samba authentication
00738   succeeded, this would indicate that the user's account is disabled,
00739   time restrictions are in place or some other password policy
00740   violation.
00741 *********************************************************************/
00742 
00743 static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
00744                                         struct samu *sam_acct, BOOL success)
00745 {
00746         struct ldapsam_privates *ldap_state;
00747 
00748         if ((!methods) || (!sam_acct)) {
00749                 DEBUG(3,("pdb_nds_update_login_attempts: invalid parameter.\n"));
00750                 return NT_STATUS_MEMORY_NOT_ALLOCATED;
00751         }
00752 
00753         ldap_state = (struct ldapsam_privates *)methods->private_data;
00754 
00755         if (ldap_state) {
00756                 /* Attempt simple bind with user credentials to update eDirectory
00757                    password policy */
00758                 int rc = 0;
00759                 char *dn;
00760                 LDAPMessage *result = NULL;
00761                 LDAPMessage *entry = NULL;
00762                 const char **attr_list;
00763                 size_t pwd_len;
00764                 char clear_text_pw[512];
00765                 LDAP *ld = NULL;
00766                 const char *username = pdb_get_username(sam_acct);
00767                 BOOL got_clear_text_pw = False;
00768 
00769                 DEBUG(5,("pdb_nds_update_login_attempts: %s login for %s\n",
00770                                 success ? "Successful" : "Failed", username));
00771 
00772                 result = (LDAPMessage *)pdb_get_backend_private_data(sam_acct, methods);
00773                 if (!result) {
00774                         attr_list = get_userattr_list(NULL,
00775                                                       ldap_state->schema_ver);
00776                         rc = ldapsam_search_suffix_by_name(ldap_state, username, &result, attr_list );
00777                         TALLOC_FREE( attr_list );
00778                         if (rc != LDAP_SUCCESS) {
00779                                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
00780                         }
00781                         pdb_set_backend_private_data(sam_acct, result, NULL,
00782                                                      methods, PDB_CHANGED);
00783                         talloc_autofree_ldapmsg(sam_acct, result);
00784                 }
00785 
00786                 if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
00787                         DEBUG(0, ("pdb_nds_update_login_attempts: No user to modify!\n"));
00788                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
00789                 }
00790 
00791                 entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
00792                 dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
00793                 if (!dn) {
00794                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
00795                 }
00796 
00797                 DEBUG(3, ("pdb_nds_update_login_attempts: username %s found dn '%s'\n", username, dn));
00798 
00799                 pwd_len = sizeof(clear_text_pw);
00800                 if (success == True) {
00801                         if (pdb_nds_get_password(ldap_state->smbldap_state, dn, &pwd_len, clear_text_pw) == LDAP_SUCCESS) {
00802                                 /* Got clear text password. Use simple ldap bind */
00803                                 got_clear_text_pw = True;
00804                         }
00805                 } else {
00806                         generate_random_buffer((unsigned char *)clear_text_pw, 24);
00807                         clear_text_pw[24] = '\0';
00808                         DEBUG(5,("pdb_nds_update_login_attempts: using random password %s\n", clear_text_pw));
00809                 }
00810 
00811                 if((success != True) || (got_clear_text_pw == True)) {
00812                         
00813                         rc = smb_ldap_setup_full_conn(&ld, ldap_state->location);
00814                         if (rc) {
00815                                 return NT_STATUS_INVALID_CONNECTION;
00816                         }
00817 
00818                         /* Attempt simple bind with real or bogus password */
00819                         rc = ldap_simple_bind_s(ld, dn, clear_text_pw);
00820                         ldap_unbind(ld);
00821                         if (rc == LDAP_SUCCESS) {
00822                                 DEBUG(5,("pdb_nds_update_login_attempts: ldap_simple_bind_s Successful for %s\n", username));
00823                         } else {
00824                                 NTSTATUS nt_status = NT_STATUS_ACCOUNT_RESTRICTION;
00825                                 DEBUG(5,("pdb_nds_update_login_attempts: ldap_simple_bind_s Failed for %s\n", username));
00826                                 switch(rc) {
00827                                         case LDAP_INVALID_CREDENTIALS:
00828                                                 nt_status = NT_STATUS_WRONG_PASSWORD;
00829                                                 break;
00830                                         case LDAP_UNWILLING_TO_PERFORM:
00831                                                 /* eDir returns this if the account was disabled. */
00832                                                 /* The problem is we don't know if the given
00833                                                    password was correct for this account or
00834                                                    not. We have to return more info than we
00835                                                    should and tell the client NT_STATUS_ACCOUNT_DISABLED
00836                                                    so they don't think the password was bad. JRA. */
00837                                                 nt_status = NT_STATUS_ACCOUNT_DISABLED;
00838                                                 break;
00839                                         default:
00840                                                 break;
00841                                 }
00842                                 return nt_status;
00843                         }
00844                 }
00845         }
00846         
00847         return NT_STATUS_OK;
00848 }
00849 
00850 /**********************************************************************
00851  Intitalise the parts of the pdb_methods structuire that are common 
00852  to NDS_ldapsam modes
00853  *********************************************************************/
00854 
00855 static NTSTATUS pdb_init_NDS_ldapsam_common(struct pdb_methods **pdb_method, const char *location)
00856 {
00857         struct ldapsam_privates *ldap_state =
00858                 (struct ldapsam_privates *)((*pdb_method)->private_data);
00859 
00860         /* Mark this as eDirectory ldap */
00861         ldap_state->is_nds_ldap = True;
00862 
00863         /* Add pdb_nds specific method for updating login attempts. */
00864         (*pdb_method)->update_login_attempts = pdb_nds_update_login_attempts;
00865 
00866         /* Save location for use in pdb_nds_update_login_attempts */
00867         ldap_state->location = SMB_STRDUP(location);
00868 
00869         return NT_STATUS_OK;
00870 }
00871 
00872 
00873 /**********************************************************************
00874  Initialise the 'nds compat' mode for pdb_ldap
00875  *********************************************************************/
00876 
00877 static NTSTATUS pdb_init_NDS_ldapsam_compat(struct pdb_methods **pdb_method, const char *location)
00878 {
00879         NTSTATUS nt_status = pdb_init_ldapsam_compat(pdb_method, location);
00880 
00881         (*pdb_method)->name = "NDS_ldapsam_compat";
00882 
00883         pdb_init_NDS_ldapsam_common(pdb_method, location);
00884 
00885         return nt_status;
00886 }
00887 
00888 
00889 /**********************************************************************
00890  Initialise the 'nds' normal mode for pdb_ldap
00891  *********************************************************************/
00892 
00893 static NTSTATUS pdb_init_NDS_ldapsam(struct pdb_methods **pdb_method, const char *location)
00894 {
00895         NTSTATUS nt_status = pdb_init_ldapsam(pdb_method, location);
00896 
00897         (*pdb_method)->name = "NDS_ldapsam";
00898 
00899         pdb_init_NDS_ldapsam_common(pdb_method, location);
00900 
00901         return nt_status;
00902 }
00903 
00904 NTSTATUS pdb_nds_init(void)
00905 {
00906         NTSTATUS nt_status;
00907         if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "NDS_ldapsam", pdb_init_NDS_ldapsam)))
00908                 return nt_status;
00909 
00910         if (!NT_STATUS_IS_OK(nt_status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "NDS_ldapsam_compat", pdb_init_NDS_ldapsam_compat)))
00911                 return nt_status;
00912 
00913         return NT_STATUS_OK;
00914 }

Sambaに対してSat Aug 29 21:23:12 2009に生成されました。  doxygen 1.4.7