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