LCOV - code coverage report
Current view: top level - source3/passdb - pdb_nds.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 4 363 1.1 %
Date: 2024-04-21 15:09:00 Functions: 1 13 7.7 %

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

Generated by: LCOV version 1.14