add support for "sambaPwdMustChange"; add support for back-config

This commit is contained in:
Pierangelo Masarati 2005-11-12 16:18:09 +00:00
parent ee8a946e8f
commit 29fab9cfd4
2 changed files with 418 additions and 44 deletions

View file

@ -42,7 +42,38 @@ To use the overlay, add:
to your slapd configuration file. (You should obtain the necessary schema
files from the Heimdal and/or Samba distributions. At this time, there
are several known errors in these schema files that you will have to
correct before they will load in slapd.)
correct before they will load in slapd. As of Samba 3.0 the schema looks
fine as shipped.)
All modules compiled in (i.e. krb5 and samba) are enabled; the statement
smbk5pwd-enable <module>
can be used to enable only the desired one(s); legal values for <module>
are "krb5" and "samba", if they are respectively enabled by defining
DO_KRB5 and DO_SAMBA.
The samba module also supports the
smbk5pwd-must-change <seconds>
which sets the "sambaPwdMustChange" attribute accordingly to force passwd
expiry. A value of 0 disables this feature.
The overlay now supports table-driven configuration, and thus can be run-time
loaded and configured via back-config. The layout of the entry is
# {0}smbk5pwd, {1}bdb, config
dn: olcOverlay={0}smbk5pwd,olcDatabase={1}bdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcSmbK5PwdConfig
olcOverlay: {0}smbk5pwd
olcSmbK5PwdEnable: krb5
olcSmbK5PwdEnable: samba
olcSmbK5PwdMustChange: 2592000
which enables both krb5 and samba modules with a password expiry time
of 30 days.
The provided Makefile builds both Kerberos and Samba support by default.
You must edit the Makefile to insure that the correct include and library

View file

@ -25,6 +25,8 @@
#include <ac/errno.h>
#include <ac/string.h>
#include "config.h"
#ifdef DO_KRB5
#include <lber.h>
#include <lber_pvt.h>
@ -62,16 +64,41 @@ static ObjectClass *oc_krb5KDCEntry;
static AttributeDescription *ad_sambaLMPassword;
static AttributeDescription *ad_sambaNTPassword;
static AttributeDescription *ad_sambaPwdLastSet;
static AttributeDescription *ad_sambaPwdMustChange;
static ObjectClass *oc_sambaSamAccount;
#endif
#if 0
static void smbk5pwd_destroy() {
kadm5_destroy(kadm_context);
krb5_free_context(context);
}
/* Per-instance configuration information */
typedef struct smbk5pwd_t {
unsigned mode;
#define SMBK5PWD_F_KRB5 (0x1U)
#define SMBK5PWD_F_SAMBA (0x2U)
#define SMBK5PWD_DO_KRB5(pi) ((pi)->mode & SMBK5PWD_F_KRB5)
#define SMBK5PWD_DO_SAMBA(pi) ((pi)->mode & SMBK5PWD_F_SAMBA)
#ifdef DO_KRB5
/* nothing yet */
#endif
#ifdef DO_SAMBA
/* How many seconds before forcing a password change? */
time_t smb_must_change;
#endif
} smbk5pwd_t;
static const unsigned SMBK5PWD_F_ALL =
0
#ifdef DO_KRB5
| SMBK5PWD_F_KRB5
#endif
#ifdef DO_SAMBA
| SMBK5PWD_F_SAMBA
#endif
;
static int smbk5pwd_modules_init( smbk5pwd_t *pi );
#ifdef DO_SAMBA
static const char hex[] = "0123456789abcdef";
@ -312,6 +339,7 @@ static int smbk5pwd_exop_passwd(
Entry *e;
Modifications *ml;
slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
smbk5pwd_t *pi = on->on_bi.bi_private;
/* Not the operation we expected, pass it on... */
if ( ber_bvcmp( &slap_EXOP_MODIFY_PASSWD, &op->ore_reqoid ) ) {
@ -331,6 +359,8 @@ static int smbk5pwd_exop_passwd(
int kvno, i;
Attribute *a;
if ( !SMBK5PWD_DO_KRB5( pi ) ) break;
if ( !is_entry_objectclass(e, oc_krb5KDCEntry, 0 ) ) break;
a = attr_find( e->e_attrs, ad_krb5PrincipalName );
@ -402,12 +432,12 @@ static int smbk5pwd_exop_passwd(
"%d", kvno+1 );
BER_BVZERO( &ml->sml_values[1] );
ml->sml_nvalues = NULL;
} while(0);
} while ( 0 );
#endif /* DO_KRB5 */
#ifdef DO_SAMBA
/* Samba stuff */
if ( is_entry_objectclass(e, oc_sambaSamAccount, 0 ) ) {
if ( SMBK5PWD_DO_SAMBA( pi ) && is_entry_objectclass(e, oc_sambaSamAccount, 0 ) ) {
struct berval *keys;
ber_len_t j,l;
wchar_t *wcs, wc;
@ -494,6 +524,28 @@ static int smbk5pwd_exop_passwd(
#endif
ml->sml_values = keys;
ml->sml_nvalues = NULL;
if (pi->smb_must_change)
{
ml = ch_malloc(sizeof(Modifications));
ml->sml_next = qpw->rs_mods;
qpw->rs_mods = ml;
keys = ch_malloc( 2 * sizeof(struct berval) );
keys[0].bv_val = ch_malloc( STRLENOF( "9223372036854775807L" ) + 1 );
keys[0].bv_len = snprintf(keys[0].bv_val,
STRLENOF( "9223372036854775807L" ) + 1,
"%ld", slap_get_time() + pi->smb_must_change);
BER_BVZERO( &keys[1] );
ml->sml_desc = ad_sambaPwdMustChange;
ml->sml_op = LDAP_MOD_REPLACE;
#ifdef SLAP_MOD_INTERNAL
ml->sml_flags = SLAP_MOD_INTERNAL;
#endif
ml->sml_values = keys;
ml->sml_nvalues = NULL;
}
}
#endif /* DO_SAMBA */
be_entry_release_r( op, e );
@ -503,67 +555,358 @@ static int smbk5pwd_exop_passwd(
static slap_overinst smbk5pwd;
int smbk5pwd_init() {
int rc;
const char *text;
/* back-config stuff */
enum {
PC_SMB_MUST_CHANGE = 1,
PC_SMB_ENABLE
};
#ifdef DO_KRB5
krb5_error_code ret;
extern HDB * _kadm5_s_get_db(void *);
static ConfigDriver smbk5pwd_cf_func;
/* Make sure all of our necessary schema items are loaded */
oc_krb5KDCEntry = oc_find("krb5KDCEntry");
if ( !oc_krb5KDCEntry ) return -1;
/*
* NOTE: uses OID arcs OLcfgOvAt:6 and OLcfgOvOc:6
*/
rc = slap_str2ad( "krb5Key", &ad_krb5Key, &text );
if ( rc ) return rc;
rc = slap_str2ad( "krb5KeyVersionNumber", &ad_krb5KeyVersionNumber, &text );
if ( rc ) return rc;
rc = slap_str2ad( "krb5PrincipalName", &ad_krb5PrincipalName, &text );
if ( rc ) return rc;
static ConfigTable smbk5pwd_cfats[] = {
{ "smbk5pwd-enable", "arg",
2, 0, 0, ARG_MAGIC|PC_SMB_ENABLE, smbk5pwd_cf_func,
"( OLcfgOvAt:6.1 NAME 'olcSmbK5PwdEnable' "
"DESC 'Modules to be enabled' "
"SYNTAX OMsDirectoryString )", NULL, NULL },
{ "smbk5pwd-must-change", "time",
2, 2, 0, ARG_MAGIC|ARG_INT|PC_SMB_MUST_CHANGE, smbk5pwd_cf_func,
"( OLcfgOvAt:6.2 NAME 'olcSmbK5PwdMustChange' "
"DESC 'Credentials validity interval' "
"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
/* Initialize Kerberos context */
ret = krb5_init_context(&context);
if (ret) {
return -1;
{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
};
static ConfigOCs smbk5pwd_cfocs[] = {
{ "( OLcfgOvOc:6.1 "
"NAME 'olcSmbK5PwdConfig' "
"DESC 'smbk5pwd overlay configuration' "
"SUP olcOverlayConfig "
"MAY ( "
"olcSmbK5PwdEnable "
"$ olcSmbK5PwdMustChange "
") )", Cft_Overlay, smbk5pwd_cfats },
{ NULL, 0, NULL }
};
/*
* add here other functionalities; handle their initialization
* as appropriate in FIXME
*/
static slap_verbmasks smbk5pwd_modules[] = {
{ BER_BVC( "krb5" ), SMBK5PWD_F_KRB5 },
{ BER_BVC( "samba" ), SMBK5PWD_F_SAMBA },
{ BER_BVNULL, -1 }
};
static int
smbk5pwd_cf_func( ConfigArgs *c )
{
slap_overinst *on = (slap_overinst *)c->bi;
int rc = 0;
smbk5pwd_t *pi = on->on_bi.bi_private;
if ( c->op == SLAP_CONFIG_EMIT ) {
switch( c->type ) {
case PC_SMB_MUST_CHANGE:
#ifdef DO_SAMBA
c->value_int = pi->smb_must_change;
#else /* ! DO_SAMBA */
c->value_int = 0;
#endif /* ! DO_SAMBA */
break;
case PC_SMB_ENABLE:
c->rvalue_vals = NULL;
if ( pi->mode ) {
mask_to_verbs( smbk5pwd_modules, pi->mode, &c->rvalue_vals );
if ( c->rvalue_vals == NULL ) {
rc = 1;
}
}
break;
default:
assert( 0 );
rc = 1;
}
return rc;
} else if ( c->op == LDAP_MOD_DELETE ) {
switch( c->type ) {
case PC_SMB_MUST_CHANGE:
break;
case PC_SMB_ENABLE:
if ( !c->line ) {
pi->mode = 0;
} else {
slap_mask_t m;
m = verb_to_mask( c->line, smbk5pwd_modules );
pi->mode &= ~m;
}
break;
default:
assert( 0 );
rc = 1;
}
return rc;
}
ret = kadm5_s_init_with_password_ctx( context,
KADM5_ADMIN_SERVICE,
NULL,
KADM5_ADMIN_SERVICE,
&conf, 0, 0, &kadm_context );
switch( c->type ) {
case PC_SMB_MUST_CHANGE:
#ifdef DO_SAMBA
pi->smb_must_change = c->value_int;
#else /* ! DO_SAMBA */
Debug( LDAP_DEBUG_ANY, "%s: smbk5pwd: "
"<%s> only meaningful "
"when compiled with -DDO_SAMBA.\n",
c->log, c->argv[ 0 ], 0 );
return 1;
#endif /* ! DO_SAMBA */
break;
case PC_SMB_ENABLE: {
slap_mask_t m;
rc = verbs_to_mask( c->argc, c->argv, smbk5pwd_modules, &m );
if ( rc ) {
Debug( LDAP_DEBUG_ANY, "%s: smbk5pwd: "
"<%s> unknown module \"%s\".\n",
c->log, c->argv[ 0 ], c->argv[ rc ] );
return 1;
}
pi->mode |= m;
#ifndef DO_KRB5
if ( SMBK5PWD_DO_KRB5( pi ) ) {
Debug( LDAP_DEBUG_ANY, "%s: smbk5pwd: "
"<%s> module \"%s\" only allowed when compiled with -DDO_KRB5.\n",
c->log, c->argv[ 0 ], c->argv[ i ] );
return 1;
}
#endif /* ! DO_KRB5 */
#ifndef DO_SAMBA
if ( SMBK5PWD_DO_SAMBA( pi ) ) {
Debug( LDAP_DEBUG_ANY, "%s: smbk5pwd: "
"<%s> module \"%s\" only allowed when compiled with -DDO_SAMBA.\n",
c->log, c->argv[ 0 ], c->argv[ i ] );
return 1;
}
#endif /* ! DO_SAMBA */
{
BackendDB db = *c->be;
db.bd_info = (BackendInfo *)on;
rc = smbk5pwd_modules_init( pi );
if ( rc ) {
return 1;
}
}
} break;
default:
assert( 0 );
return 1;
}
return rc;
}
static int
smbk5pwd_modules_init( smbk5pwd_t *pi )
{
int rc;
const char *text;
#ifdef DO_KRB5
if ( SMBK5PWD_DO_KRB5( pi ) && oc_krb5KDCEntry == NULL ) {
krb5_error_code ret;
extern HDB *_kadm5_s_get_db(void *);
/* Make sure all of our necessary schema items are loaded */
oc_krb5KDCEntry = oc_find("krb5KDCEntry");
if ( !oc_krb5KDCEntry ) {
Debug( LDAP_DEBUG_ANY, "smbk5pwd: "
"unable to find \"krb5KDCEntry\" objectClass.\n",
0, 0, 0 );
return -1;
}
rc = slap_str2ad( "krb5Key", &ad_krb5Key, &text );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "smbk5pwd: "
"unable to find \"krb5Key\" attributeType: %s (%d).\n",
text, rc, 0 );
return rc;
}
rc = slap_str2ad( "krb5KeyVersionNumber", &ad_krb5KeyVersionNumber, &text );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "smbk5pwd: "
"unable to find \"krb5KeyVersionNumber\" attributeType: %s (%d).\n",
text, rc, 0 );
return rc;
}
rc = slap_str2ad( "krb5PrincipalName", &ad_krb5PrincipalName, &text );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "smbk5pwd: "
"unable to find \"krb5PrincipalName\" attributeType: %s (%d).\n",
text, rc, 0 );
return rc;
}
/* Initialize Kerberos context */
ret = krb5_init_context(&context);
if (ret) {
Debug( LDAP_DEBUG_ANY, "smbk5pwd: "
"unable to initialize krb5 context.\n",
0, 0, 0 );
return -1;
}
ret = kadm5_s_init_with_password_ctx( context,
KADM5_ADMIN_SERVICE,
NULL,
KADM5_ADMIN_SERVICE,
&conf, 0, 0, &kadm_context );
db = _kadm5_s_get_db(kadm_context);
db = _kadm5_s_get_db(kadm_context);
}
#endif /* DO_KRB5 */
#ifdef DO_SAMBA
oc_sambaSamAccount = oc_find("sambaSamAccount");
if ( !oc_sambaSamAccount ) return -1;
if ( SMBK5PWD_DO_SAMBA( pi ) && oc_sambaSamAccount == NULL ) {
oc_sambaSamAccount = oc_find( "sambaSamAccount" );
if ( !oc_sambaSamAccount ) {
Debug( LDAP_DEBUG_ANY, "smbk5pwd: "
"unable to find \"sambaSamAccount\" objectClass.\n",
0, 0, 0 );
return -1;
}
rc = slap_str2ad( "sambaLMPassword", &ad_sambaLMPassword, &text );
if ( rc ) return rc;
rc = slap_str2ad( "sambaNTPassword", &ad_sambaNTPassword, &text );
if ( rc ) return rc;
rc = slap_str2ad( "sambaPwdLastSet", &ad_sambaPwdLastSet, &text );
if ( rc ) return rc;
rc = slap_str2ad( "sambaLMPassword", &ad_sambaLMPassword, &text );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "smbk5pwd: "
"unable to find \"sambaLMPassword\" attributeType: %s (%d).\n",
text, rc, 0 );
return rc;
}
rc = slap_str2ad( "sambaNTPassword", &ad_sambaNTPassword, &text );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "smbk5pwd: "
"unable to find \"sambaLMPassword\" attributeType: %s (%d).\n",
text, rc, 0 );
return rc;
}
rc = slap_str2ad( "sambaPwdLastSet", &ad_sambaPwdLastSet, &text );
if ( rc != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "smbk5pwd: "
"unable to find \"sambaLMPassword\" attributeType: %s (%d).\n",
text, rc, 0 );
return rc;
}
}
#endif /* DO_SAMBA */
smbk5pwd.on_bi.bi_type = "smbk5pwd";
smbk5pwd.on_bi.bi_extended = smbk5pwd_exop_passwd;
return 0;
}
static int
smbk5pwd_db_init(BackendDB *be)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
smbk5pwd_t *pi;
pi = ch_calloc( 1, sizeof( smbk5pwd_t ) );
if ( pi == NULL ) {
return 1;
}
on->on_bi.bi_private = (void *)pi;
return 0;
}
static int
smbk5pwd_db_open(BackendDB *be)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
smbk5pwd_t *pi = (smbk5pwd_t *)on->on_bi.bi_private;
int rc;
if ( pi->mode == 0 ) {
pi->mode = SMBK5PWD_F_ALL;
}
rc = smbk5pwd_modules_init( pi );
if ( rc ) {
return rc;
}
return 0;
}
static int
smbk5pwd_db_destroy(BackendDB *be)
{
slap_overinst *on = (slap_overinst *)be->bd_info;
smbk5pwd_t *pi = (smbk5pwd_t *)on->on_bi.bi_private;
if ( pi ) {
ch_free( pi );
}
return 0;
}
int
smbk5pwd_initialize(void)
{
int rc;
smbk5pwd.on_bi.bi_type = "smbk5pwd";
smbk5pwd.on_bi.bi_db_init = smbk5pwd_db_init;
smbk5pwd.on_bi.bi_db_open = smbk5pwd_db_open;
smbk5pwd.on_bi.bi_db_destroy = smbk5pwd_db_destroy;
smbk5pwd.on_bi.bi_extended = smbk5pwd_exop_passwd;
#ifdef DO_KRB5
smbk5pwd.on_bi.bi_op_bind = smbk5pwd_op_bind;
lutil_passwd_add( (struct berval *)&k5key_scheme, k5key_chk, k5key_hash );
#endif
smbk5pwd.on_bi.bi_cf_ocs = smbk5pwd_cfocs;
rc = config_register_schema( smbk5pwd_cfats, smbk5pwd_cfocs );
if ( rc ) {
return rc;
}
return overlay_register( &smbk5pwd );
}
#if SLAPD_OVER_SMBK5PWD == SLAPD_MOD_DYNAMIC
int init_module(int argc, char *argv[]) {
return smbk5pwd_init();
return smbk5pwd_initialize();
}
#endif