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