Line 0
Link Here
|
|
|
1 |
/* smbk5pwd.c - Overlay for managing Samba and Heimdal passwords */ |
2 |
/* $OpenLDAP: pkg/ldap/contrib/slapd-modules/smbk5pwd/smbk5pwd.c,v 1.1.2.5 2005/08/12 15:25:19 kurt Exp $ */ |
3 |
/* |
4 |
* Copyright 2004-2005 by Howard Chu, Symas Corp. |
5 |
* All rights reserved. |
6 |
* |
7 |
* Redistribution and use in source and binary forms, with or without |
8 |
* modification, are permitted only as authorized by the OpenLDAP |
9 |
* Public License. |
10 |
* |
11 |
* A copy of this license is available in the file LICENSE in the |
12 |
* top-level directory of the distribution or, alternatively, at |
13 |
* <http://www.OpenLDAP.org/license.html>. |
14 |
*/ |
15 |
|
16 |
#include <portable.h> |
17 |
|
18 |
#ifndef SLAPD_OVER_SMBK5PWD |
19 |
#define SLAPD_OVER_SMBK5PWD SLAPD_MOD_DYNAMIC |
20 |
#endif |
21 |
|
22 |
#ifdef SLAPD_OVER_SMBK5PWD |
23 |
|
24 |
#include <slap.h> |
25 |
#include <ac/errno.h> |
26 |
|
27 |
#ifdef DO_KRB5 |
28 |
#include <ac/string.h> |
29 |
#include <lber.h> |
30 |
#include <lber_pvt.h> |
31 |
#include <lutil.h> |
32 |
|
33 |
/* make ASN1_MALLOC_ENCODE use our allocator */ |
34 |
#define malloc ch_malloc |
35 |
|
36 |
#include <krb5.h> |
37 |
#include <kadm5/admin.h> |
38 |
#include <hdb.h> |
39 |
|
40 |
#ifndef HDB_INTERFACE_VERSION |
41 |
#define HDB_MASTER_KEY_SET master_key_set |
42 |
#else |
43 |
#define HDB_MASTER_KEY_SET hdb_master_key_set |
44 |
#endif |
45 |
|
46 |
static krb5_context context; |
47 |
static void *kadm_context; |
48 |
static kadm5_config_params conf; |
49 |
static HDB *db; |
50 |
|
51 |
static AttributeDescription *ad_krb5Key; |
52 |
static AttributeDescription *ad_krb5KeyVersionNumber; |
53 |
static AttributeDescription *ad_krb5PrincipalName; |
54 |
static ObjectClass *oc_krb5KDCEntry; |
55 |
#endif |
56 |
|
57 |
#ifdef DO_SAMBA |
58 |
#include <openssl/des.h> |
59 |
#include <openssl/md4.h> |
60 |
|
61 |
static AttributeDescription *ad_sambaLMPassword; |
62 |
static AttributeDescription *ad_sambaNTPassword; |
63 |
static AttributeDescription *ad_sambaPwdLastSet; |
64 |
static ObjectClass *oc_sambaSamAccount; |
65 |
#endif |
66 |
|
67 |
#if 0 |
68 |
static void smbk5pwd_destroy() { |
69 |
kadm5_destroy(kadm_context); |
70 |
krb5_free_context(context); |
71 |
} |
72 |
#endif |
73 |
|
74 |
#ifdef DO_SAMBA |
75 |
static const char hex[] = "0123456789abcdef"; |
76 |
|
77 |
/* From liblutil/passwd.c... */ |
78 |
static void lmPasswd_to_key( |
79 |
const char *lmPasswd, |
80 |
des_cblock *key) |
81 |
{ |
82 |
const unsigned char *lpw = (const unsigned char *)lmPasswd; |
83 |
unsigned char *k = (unsigned char *)key; |
84 |
|
85 |
/* make room for parity bits */ |
86 |
k[0] = lpw[0]; |
87 |
k[1] = ((lpw[0]&0x01)<<7) | (lpw[1]>>1); |
88 |
k[2] = ((lpw[1]&0x03)<<6) | (lpw[2]>>2); |
89 |
k[3] = ((lpw[2]&0x07)<<5) | (lpw[3]>>3); |
90 |
k[4] = ((lpw[3]&0x0F)<<4) | (lpw[4]>>4); |
91 |
k[5] = ((lpw[4]&0x1F)<<3) | (lpw[5]>>5); |
92 |
k[6] = ((lpw[5]&0x3F)<<2) | (lpw[6]>>6); |
93 |
k[7] = ((lpw[6]&0x7F)<<1); |
94 |
|
95 |
des_set_odd_parity( key ); |
96 |
} |
97 |
|
98 |
#define MAX_PWLEN 256 |
99 |
#define HASHLEN 16 |
100 |
|
101 |
static void hexify( |
102 |
const char in[HASHLEN], |
103 |
struct berval *out |
104 |
) |
105 |
{ |
106 |
int i; |
107 |
char *a; |
108 |
unsigned char *b; |
109 |
|
110 |
out->bv_val = ch_malloc(HASHLEN*2 + 1); |
111 |
out->bv_len = HASHLEN*2; |
112 |
|
113 |
a = out->bv_val; |
114 |
b = (unsigned char *)in; |
115 |
for (i=0; i<HASHLEN; i++) { |
116 |
*a++ = hex[*b >> 4]; |
117 |
*a++ = hex[*b++ & 0x0f]; |
118 |
} |
119 |
*a++ = '\0'; |
120 |
} |
121 |
|
122 |
static void lmhash( |
123 |
struct berval *passwd, |
124 |
struct berval *hash |
125 |
) |
126 |
{ |
127 |
char UcasePassword[15]; |
128 |
des_cblock key; |
129 |
des_key_schedule schedule; |
130 |
des_cblock StdText = "KGS!@#$%"; |
131 |
des_cblock hbuf[2]; |
132 |
|
133 |
strncpy( UcasePassword, passwd->bv_val, 14 ); |
134 |
UcasePassword[14] = '\0'; |
135 |
ldap_pvt_str2upper( UcasePassword ); |
136 |
|
137 |
lmPasswd_to_key( UcasePassword, &key ); |
138 |
des_set_key_unchecked( &key, schedule ); |
139 |
des_ecb_encrypt( &StdText, &hbuf[0], schedule , DES_ENCRYPT ); |
140 |
|
141 |
lmPasswd_to_key( &UcasePassword[7], &key ); |
142 |
des_set_key_unchecked( &key, schedule ); |
143 |
des_ecb_encrypt( &StdText, &hbuf[1], schedule , DES_ENCRYPT ); |
144 |
|
145 |
hexify( (char *)hbuf, hash ); |
146 |
} |
147 |
|
148 |
static void nthash( |
149 |
struct berval *passwd, |
150 |
struct berval *hash |
151 |
) |
152 |
{ |
153 |
/* Windows currently only allows 14 character passwords, but |
154 |
* may support up to 256 in the future. We assume this means |
155 |
* 256 UCS2 characters, not 256 bytes... |
156 |
*/ |
157 |
char hbuf[HASHLEN]; |
158 |
int i; |
159 |
MD4_CTX ctx; |
160 |
|
161 |
if (passwd->bv_len > MAX_PWLEN*2) |
162 |
passwd->bv_len = MAX_PWLEN*2; |
163 |
|
164 |
MD4_Init( &ctx ); |
165 |
MD4_Update( &ctx, passwd->bv_val, passwd->bv_len ); |
166 |
MD4_Final( (unsigned char *)hbuf, &ctx ); |
167 |
|
168 |
hexify( hbuf, hash ); |
169 |
} |
170 |
#endif /* DO_SAMBA */ |
171 |
|
172 |
#ifdef DO_KRB5 |
173 |
|
174 |
static int smbk5pwd_op_cleanup( |
175 |
Operation *op, |
176 |
SlapReply *rs ) |
177 |
{ |
178 |
slap_callback *cb; |
179 |
|
180 |
/* clear out the current key */ |
181 |
ldap_pvt_thread_pool_setkey( op->o_threadctx, smbk5pwd_op_cleanup, |
182 |
NULL, NULL ); |
183 |
|
184 |
/* free the callback */ |
185 |
cb = op->o_callback; |
186 |
op->o_callback = cb->sc_next; |
187 |
op->o_tmpfree( cb, op->o_tmpmemctx ); |
188 |
return 0; |
189 |
} |
190 |
|
191 |
static int smbk5pwd_op_bind( |
192 |
Operation *op, |
193 |
SlapReply *rs ) |
194 |
{ |
195 |
/* If this is a simple Bind, stash the Op pointer so our chk |
196 |
* function can find it. Set a cleanup callback to clear it |
197 |
* out when the Bind completes. |
198 |
*/ |
199 |
if ( op->oq_bind.rb_method == LDAP_AUTH_SIMPLE ) { |
200 |
slap_callback *cb; |
201 |
ldap_pvt_thread_pool_setkey( op->o_threadctx, smbk5pwd_op_cleanup, op, |
202 |
NULL ); |
203 |
cb = op->o_tmpcalloc( 1, sizeof(slap_callback), op->o_tmpmemctx ); |
204 |
cb->sc_cleanup = smbk5pwd_op_cleanup; |
205 |
cb->sc_next = op->o_callback; |
206 |
op->o_callback = cb; |
207 |
} |
208 |
return SLAP_CB_CONTINUE; |
209 |
} |
210 |
|
211 |
static LUTIL_PASSWD_CHK_FUNC k5key_chk; |
212 |
static LUTIL_PASSWD_HASH_FUNC k5key_hash; |
213 |
static const struct berval k5key_scheme = BER_BVC("{K5KEY}"); |
214 |
|
215 |
/* This password scheme stores no data in the userPassword attribute |
216 |
* other than the scheme name. It assumes the invoking entry is a |
217 |
* krb5KDCentry and compares the passed-in credentials against the |
218 |
* krb5Key attribute. The krb5Key may be multi-valued, but they are |
219 |
* simply multiple keytypes generated from the same input string, so |
220 |
* only the first value needs to be compared here. |
221 |
* |
222 |
* Since the lutil_passwd API doesn't pass the Entry object in, we |
223 |
* have to fetch it ourselves in order to get access to the other |
224 |
* attributes. We accomplish this with the help of the overlay's Bind |
225 |
* function, which stores the current Operation pointer in thread-specific |
226 |
* storage so we can retrieve it here. The Operation provides all |
227 |
* the necessary context for us to get Entry from the database. |
228 |
*/ |
229 |
static int k5key_chk( |
230 |
const struct berval *sc, |
231 |
const struct berval *passwd, |
232 |
const struct berval *cred, |
233 |
const char **text ) |
234 |
{ |
235 |
void *ctx; |
236 |
Operation *op; |
237 |
int rc; |
238 |
Entry *e; |
239 |
Attribute *a; |
240 |
krb5_error_code ret; |
241 |
krb5_keyblock key; |
242 |
krb5_salt salt; |
243 |
hdb_entry ent; |
244 |
|
245 |
/* Find our thread context, find our Operation */ |
246 |
ctx = ldap_pvt_thread_pool_context(); |
247 |
|
248 |
if ( ldap_pvt_thread_pool_getkey( ctx, smbk5pwd_op_cleanup, (void **)&op, NULL ) || |
249 |
!op ) |
250 |
return LUTIL_PASSWD_ERR; |
251 |
|
252 |
rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e ); |
253 |
if ( rc != LDAP_SUCCESS ) return LUTIL_PASSWD_ERR; |
254 |
|
255 |
rc = LUTIL_PASSWD_ERR; |
256 |
do { |
257 |
size_t l; |
258 |
Key ekey = {0}; |
259 |
|
260 |
a = attr_find( e->e_attrs, ad_krb5PrincipalName ); |
261 |
if (!a ) break; |
262 |
|
263 |
memset( &ent, 0, sizeof(ent) ); |
264 |
ret = krb5_parse_name(context, a->a_vals[0].bv_val, &ent.principal); |
265 |
if ( ret ) break; |
266 |
krb5_get_pw_salt( context, ent.principal, &salt ); |
267 |
krb5_free_principal( context, ent.principal ); |
268 |
|
269 |
a = attr_find( e->e_attrs, ad_krb5Key ); |
270 |
if ( !a ) break; |
271 |
|
272 |
ent.keys.len = 1; |
273 |
ent.keys.val = &ekey; |
274 |
decode_Key((unsigned char *) a->a_vals[0].bv_val, |
275 |
(size_t) a->a_vals[0].bv_len, &ent.keys.val[0], &l); |
276 |
if ( db->HDB_MASTER_KEY_SET ) |
277 |
hdb_unseal_keys( context, db, &ent ); |
278 |
|
279 |
krb5_string_to_key_salt( context, ekey.key.keytype, cred->bv_val, |
280 |
salt, &key ); |
281 |
|
282 |
krb5_free_salt( context, salt ); |
283 |
|
284 |
if ( memcmp( ekey.key.keyvalue.data, key.keyvalue.data, |
285 |
key.keyvalue.length ) == 0 ) rc = LUTIL_PASSWD_OK; |
286 |
|
287 |
krb5_free_keyblock_contents( context, &key ); |
288 |
krb5_free_keyblock_contents( context, &ekey.key ); |
289 |
|
290 |
} while(0); |
291 |
be_entry_release_r( op, e ); |
292 |
return rc; |
293 |
} |
294 |
|
295 |
static int k5key_hash( |
296 |
const struct berval *scheme, |
297 |
const struct berval *passwd, |
298 |
struct berval *hash, |
299 |
const char **text ) |
300 |
{ |
301 |
ber_dupbv( hash, (struct berval *)&k5key_scheme ); |
302 |
return LUTIL_PASSWD_OK; |
303 |
} |
304 |
#endif /* DO_KRB5 */ |
305 |
|
306 |
static int smbk5pwd_exop_passwd( |
307 |
Operation *op, |
308 |
SlapReply *rs ) |
309 |
{ |
310 |
int i, rc; |
311 |
req_pwdexop_s *qpw = &op->oq_pwdexop; |
312 |
Entry *e; |
313 |
Attribute *a; |
314 |
Modifications *ml; |
315 |
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; |
316 |
|
317 |
/* Not the operation we expected, pass it on... */ |
318 |
if ( ber_bvcmp( &slap_EXOP_MODIFY_PASSWD, &op->ore_reqoid ) ) { |
319 |
return SLAP_CB_CONTINUE; |
320 |
} |
321 |
|
322 |
op->o_bd->bd_info = (BackendInfo *)on->on_info; |
323 |
rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e ); |
324 |
if ( rc != LDAP_SUCCESS ) return rc; |
325 |
|
326 |
#ifdef DO_KRB5 |
327 |
/* Kerberos stuff */ |
328 |
do { |
329 |
krb5_error_code ret; |
330 |
hdb_entry ent; |
331 |
struct berval *keys; |
332 |
int kvno; |
333 |
|
334 |
if ( !is_entry_objectclass(e, oc_krb5KDCEntry, 0 ) ) break; |
335 |
|
336 |
a = attr_find( e->e_attrs, ad_krb5PrincipalName ); |
337 |
if ( !a ) break; |
338 |
|
339 |
memset( &ent, 0, sizeof(ent) ); |
340 |
ret = krb5_parse_name(context, a->a_vals[0].bv_val, &ent.principal); |
341 |
if ( ret ) break; |
342 |
|
343 |
a = attr_find( e->e_attrs, ad_krb5KeyVersionNumber ); |
344 |
if ( a ) { |
345 |
kvno = atoi(a->a_vals[0].bv_val); |
346 |
} else { |
347 |
/* shouldn't happen, this is a required attr */ |
348 |
kvno = 0; |
349 |
} |
350 |
|
351 |
ret = _kadm5_set_keys(kadm_context, &ent, qpw->rs_new.bv_val); |
352 |
hdb_seal_keys(context, db, &ent); |
353 |
krb5_free_principal( context, ent.principal ); |
354 |
|
355 |
keys = ch_malloc( (ent.keys.len + 1) * sizeof(struct berval)); |
356 |
|
357 |
for (i = 0; i < ent.keys.len; i++) { |
358 |
unsigned char *buf; |
359 |
size_t len; |
360 |
|
361 |
ASN1_MALLOC_ENCODE(Key, buf, len, &ent.keys.val[i], &len, ret); |
362 |
if (ret != 0) |
363 |
break; |
364 |
|
365 |
keys[i].bv_val = (char *)buf; |
366 |
keys[i].bv_len = len; |
367 |
} |
368 |
keys[i].bv_val = NULL; |
369 |
keys[i].bv_len = 0; |
370 |
|
371 |
_kadm5_free_keys(kadm_context, ent.keys.len, ent.keys.val); |
372 |
|
373 |
if ( i != ent.keys.len ) { |
374 |
ber_bvarray_free( keys ); |
375 |
break; |
376 |
} |
377 |
|
378 |
ml = ch_malloc(sizeof(Modifications)); |
379 |
if (!qpw->rs_modtail) qpw->rs_modtail = &ml->sml_next; |
380 |
ml->sml_next = qpw->rs_mods; |
381 |
qpw->rs_mods = ml; |
382 |
|
383 |
ml->sml_desc = ad_krb5Key; |
384 |
ml->sml_op = LDAP_MOD_REPLACE; |
385 |
#ifdef SLAP_MOD_INTERNAL |
386 |
ml->sml_flags = SLAP_MOD_INTERNAL; |
387 |
#endif |
388 |
ml->sml_values = keys; |
389 |
ml->sml_nvalues = NULL; |
390 |
|
391 |
ml = ch_malloc(sizeof(Modifications)); |
392 |
ml->sml_next = qpw->rs_mods; |
393 |
qpw->rs_mods = ml; |
394 |
|
395 |
ml->sml_desc = ad_krb5KeyVersionNumber; |
396 |
ml->sml_op = LDAP_MOD_REPLACE; |
397 |
#ifdef SLAP_MOD_INTERNAL |
398 |
ml->sml_flags = SLAP_MOD_INTERNAL; |
399 |
#endif |
400 |
ml->sml_values = ch_malloc( 2 * sizeof(struct berval)); |
401 |
ml->sml_values[0].bv_val = ch_malloc( 64 ); |
402 |
ml->sml_values[0].bv_len = sprintf(ml->sml_values[0].bv_val, |
403 |
"%d", kvno+1 ); |
404 |
ml->sml_values[1].bv_val = NULL; |
405 |
ml->sml_values[1].bv_len = 0; |
406 |
ml->sml_nvalues = NULL; |
407 |
} while(0); |
408 |
#endif /* DO_KRB5 */ |
409 |
|
410 |
#ifdef DO_SAMBA |
411 |
/* Samba stuff */ |
412 |
if ( is_entry_objectclass(e, oc_sambaSamAccount, 0 ) ) { |
413 |
struct berval *keys; |
414 |
ber_len_t j,l; |
415 |
wchar_t *wcs, wc; |
416 |
char *c, *d; |
417 |
struct berval pwd; |
418 |
|
419 |
/* Expand incoming UTF8 string to UCS4 */ |
420 |
l = ldap_utf8_chars(qpw->rs_new.bv_val); |
421 |
wcs = ch_malloc((l+1) * sizeof(wchar_t)); |
422 |
|
423 |
ldap_x_utf8s_to_wcs( wcs, qpw->rs_new.bv_val, l ); |
424 |
|
425 |
/* Truncate UCS4 to UCS2 */ |
426 |
c = (char *)wcs; |
427 |
for (j=0; j<l; j++) { |
428 |
wc = wcs[j]; |
429 |
*c++ = wc & 0xff; |
430 |
*c++ = (wc >> 8) & 0xff; |
431 |
} |
432 |
*c++ = 0; |
433 |
pwd.bv_val = (char *)wcs; |
434 |
pwd.bv_len = l * 2; |
435 |
|
436 |
ml = ch_malloc(sizeof(Modifications)); |
437 |
if (!qpw->rs_modtail) qpw->rs_modtail = &ml->sml_next; |
438 |
ml->sml_next = qpw->rs_mods; |
439 |
qpw->rs_mods = ml; |
440 |
|
441 |
keys = ch_malloc( 2 * sizeof(struct berval) ); |
442 |
keys[1].bv_val = NULL; |
443 |
keys[1].bv_len = 0; |
444 |
nthash( &pwd, keys ); |
445 |
|
446 |
ml->sml_desc = ad_sambaNTPassword; |
447 |
ml->sml_op = LDAP_MOD_REPLACE; |
448 |
#ifdef SLAP_MOD_INTERNAL |
449 |
ml->sml_flags = SLAP_MOD_INTERNAL; |
450 |
#endif |
451 |
ml->sml_values = keys; |
452 |
ml->sml_nvalues = NULL; |
453 |
|
454 |
/* Truncate UCS2 to 8-bit ASCII */ |
455 |
c = pwd.bv_val+1; |
456 |
d = pwd.bv_val+2; |
457 |
for (j=1; j<l; j++) { |
458 |
*c++ = *d++; |
459 |
d++; |
460 |
} |
461 |
pwd.bv_len /= 2; |
462 |
pwd.bv_val[pwd.bv_len] = '\0'; |
463 |
|
464 |
ml = ch_malloc(sizeof(Modifications)); |
465 |
ml->sml_next = qpw->rs_mods; |
466 |
qpw->rs_mods = ml; |
467 |
|
468 |
keys = ch_malloc( 2 * sizeof(struct berval) ); |
469 |
keys[1].bv_val = NULL; |
470 |
keys[1].bv_len = 0; |
471 |
lmhash( &pwd, keys ); |
472 |
|
473 |
ml->sml_desc = ad_sambaLMPassword; |
474 |
ml->sml_op = LDAP_MOD_REPLACE; |
475 |
#ifdef SLAP_MOD_INTERNAL |
476 |
ml->sml_flags = SLAP_MOD_INTERNAL; |
477 |
#endif |
478 |
ml->sml_values = keys; |
479 |
ml->sml_nvalues = NULL; |
480 |
|
481 |
ch_free(wcs); |
482 |
|
483 |
ml = ch_malloc(sizeof(Modifications)); |
484 |
ml->sml_next = qpw->rs_mods; |
485 |
qpw->rs_mods = ml; |
486 |
|
487 |
keys = ch_malloc( 2 * sizeof(struct berval) ); |
488 |
keys[1].bv_val = NULL; |
489 |
keys[1].bv_len = 0; |
490 |
keys[0].bv_val = ch_malloc(16); |
491 |
keys[0].bv_len = sprintf(keys[0].bv_val, "%d", |
492 |
slap_get_time()); |
493 |
|
494 |
ml->sml_desc = ad_sambaPwdLastSet; |
495 |
ml->sml_op = LDAP_MOD_REPLACE; |
496 |
#ifdef SLAP_MOD_INTERNAL |
497 |
ml->sml_flags = SLAP_MOD_INTERNAL; |
498 |
#endif |
499 |
ml->sml_values = keys; |
500 |
ml->sml_nvalues = NULL; |
501 |
} |
502 |
#endif /* DO_SAMBA */ |
503 |
be_entry_release_r( op, e ); |
504 |
|
505 |
return SLAP_CB_CONTINUE; |
506 |
} |
507 |
|
508 |
static slap_overinst smbk5pwd; |
509 |
|
510 |
int smbk5pwd_init() { |
511 |
int rc; |
512 |
const char *text; |
513 |
|
514 |
#ifdef DO_KRB5 |
515 |
krb5_error_code ret; |
516 |
extern HDB * _kadm5_s_get_db(void *); |
517 |
|
518 |
/* Make sure all of our necessary schema items are loaded */ |
519 |
oc_krb5KDCEntry = oc_find("krb5KDCEntry"); |
520 |
if ( !oc_krb5KDCEntry ) return -1; |
521 |
|
522 |
rc = slap_str2ad( "krb5Key", &ad_krb5Key, &text ); |
523 |
if ( rc ) return rc; |
524 |
rc = slap_str2ad( "krb5KeyVersionNumber", &ad_krb5KeyVersionNumber, &text ); |
525 |
if ( rc ) return rc; |
526 |
rc = slap_str2ad( "krb5PrincipalName", &ad_krb5PrincipalName, &text ); |
527 |
if ( rc ) return rc; |
528 |
|
529 |
/* Initialize Kerberos context */ |
530 |
ret = krb5_init_context(&context); |
531 |
if (ret) { |
532 |
return -1; |
533 |
} |
534 |
|
535 |
ret = kadm5_s_init_with_password_ctx( context, |
536 |
KADM5_ADMIN_SERVICE, |
537 |
NULL, |
538 |
KADM5_ADMIN_SERVICE, |
539 |
&conf, 0, 0, &kadm_context ); |
540 |
|
541 |
db = _kadm5_s_get_db(kadm_context); |
542 |
#endif /* DO_KRB5 */ |
543 |
|
544 |
#ifdef DO_SAMBA |
545 |
oc_sambaSamAccount = oc_find("sambaSamAccount"); |
546 |
if ( !oc_sambaSamAccount ) return -1; |
547 |
|
548 |
rc = slap_str2ad( "sambaLMPassword", &ad_sambaLMPassword, &text ); |
549 |
if ( rc ) return rc; |
550 |
rc = slap_str2ad( "sambaNTPassword", &ad_sambaNTPassword, &text ); |
551 |
if ( rc ) return rc; |
552 |
rc = slap_str2ad( "sambaPwdLastSet", &ad_sambaPwdLastSet, &text ); |
553 |
if ( rc ) return rc; |
554 |
#endif /* DO_SAMBA */ |
555 |
|
556 |
smbk5pwd.on_bi.bi_type = "smbk5pwd"; |
557 |
smbk5pwd.on_bi.bi_extended = smbk5pwd_exop_passwd; |
558 |
|
559 |
#ifdef DO_KRB5 |
560 |
smbk5pwd.on_bi.bi_op_bind = smbk5pwd_op_bind; |
561 |
|
562 |
lutil_passwd_add( (struct berval *)&k5key_scheme, k5key_chk, k5key_hash ); |
563 |
#endif |
564 |
|
565 |
return overlay_register( &smbk5pwd ); |
566 |
} |
567 |
|
568 |
#if SLAPD_OVER_SMBK5PWD == SLAPD_MOD_DYNAMIC |
569 |
int init_module(int argc, char *argv[]) { |
570 |
return smbk5pwd_init(); |
571 |
} |
572 |
#endif |
573 |
|
574 |
#endif /* defined(SLAPD_OVER_SMBK5PWD) */ |