From 67d5bc650fa35de4a3af08ec0db914f49bef7cbd Mon Sep 17 00:00:00 2001 From: Jacques Vidrine Date: Thu, 12 Feb 2004 15:47:11 +0000 Subject: [PATCH] Add patch for password initialization bug. Obtained from: Samba CVS --- net/samba-devel/Makefile | 4 +- net/samba-devel/files/patch-unit_pw | 263 ++++++++++++++++++++++++++++ net/samba3/Makefile | 4 +- net/samba3/files/patch-unit_pw | 263 ++++++++++++++++++++++++++++ 4 files changed, 530 insertions(+), 4 deletions(-) create mode 100644 net/samba-devel/files/patch-unit_pw create mode 100644 net/samba3/files/patch-unit_pw diff --git a/net/samba-devel/Makefile b/net/samba-devel/Makefile index ae18a40f317e..4e087ed2bb09 100644 --- a/net/samba-devel/Makefile +++ b/net/samba-devel/Makefile @@ -7,11 +7,11 @@ PORTNAME= samba PORTVERSION= 3.0.1 -PORTREVISION= 1 +PORTREVISION= 2 PORTEPOCH= 1 CATEGORIES= net MASTER_SITES= http://us3.samba.org/samba/ftp/%SUBDIR%/ -MASTER_SITE_SUBDIR= . rc +MASTER_SITE_SUBDIR= . rc old-versions #DISTNAME= ${PORTNAME}-${PORTVERSION:S/.r/rc/} MAINTAINER= dwcjr@FreeBSD.org diff --git a/net/samba-devel/files/patch-unit_pw b/net/samba-devel/files/patch-unit_pw new file mode 100644 index 000000000000..822010cb12e3 --- /dev/null +++ b/net/samba-devel/files/patch-unit_pw @@ -0,0 +1,263 @@ +Index: source/passdb/pdb_get_set.c +=================================================================== +RCS file: /data/cvs/samba/source/passdb/pdb_get_set.c,v +retrieving revision 1.26.2.4 +diff -u -r1.26.2.4 pdb_get_set.c +--- passdb/pdb_get_set.c 7 Nov 2003 17:36:50 -0000 1.26.2.4 ++++ passdb/pdb_get_set.c 5 Feb 2004 14:43:53 -0000 +@@ -933,7 +933,11 @@ + + data_blob_clear_free(&sampass->private.nt_pw); + +- sampass->private.nt_pw = data_blob(pwd, NT_HASH_LEN); ++ if (pwd) { ++ sampass->private.nt_pw = data_blob(pwd, NT_HASH_LEN); ++ } else { ++ sampass->private.nt_pw = data_blob(NULL, 0); ++ } + + return pdb_set_init_flags(sampass, PDB_NTPASSWD, flag); + } +@@ -949,7 +953,11 @@ + + data_blob_clear_free(&sampass->private.lm_pw); + +- sampass->private.lm_pw = data_blob(pwd, LM_HASH_LEN); ++ if (pwd) { ++ sampass->private.lm_pw = data_blob(pwd, LM_HASH_LEN); ++ } else { ++ sampass->private.lm_pw = data_blob(NULL, 0); ++ } + + return pdb_set_init_flags(sampass, PDB_LMPASSWD, flag); + } +Index: source/passdb/pdb_interface.c +=================================================================== +RCS file: /data/cvs/samba/source/passdb/pdb_interface.c,v +retrieving revision 1.47.2.3 +diff -u -r1.47.2.3 pdb_interface.c +--- passdb/pdb_interface.c 8 Sep 2003 14:13:34 -0000 1.47.2.3 ++++ passdb/pdb_interface.c 5 Feb 2004 14:43:54 -0000 +@@ -36,6 +36,44 @@ + + static struct pdb_init_function_entry *pdb_find_backend_entry(const char *name); + ++/******************************************************************* ++ Clean up uninitialised passwords. The only way to tell ++ that these values are not 'real' is that they do not ++ have a valid last set time. Instead, the value is fixed at 0. ++ Therefore we use that as the key for 'is this a valid password'. ++ However, it is perfectly valid to have a 'default' last change ++ time, such LDAP with a missing attribute would produce. ++********************************************************************/ ++ ++static void pdb_force_pw_initialization(SAM_ACCOUNT *pass) ++{ ++ const char *lm_pwd, *nt_pwd; ++ ++ /* only reset a password if the last set time has been ++ explicitly been set to zero. A default last set time ++ is ignored */ ++ ++ if ( (pdb_get_init_flags(pass, PDB_PASSLASTSET) != PDB_DEFAULT) ++ && (pdb_get_pass_last_set_time(pass) == 0) ) ++ { ++ ++ if (pdb_get_init_flags(pass, PDB_LMPASSWD) != PDB_DEFAULT) ++ { ++ lm_pwd = pdb_get_lanman_passwd(pass); ++ if (lm_pwd) ++ pdb_set_lanman_passwd(pass, NULL, PDB_SET); ++ } ++ if (pdb_get_init_flags(pass, PDB_NTPASSWD) != PDB_DEFAULT) ++ { ++ nt_pwd = pdb_get_nt_passwd(pass); ++ if (nt_pwd) ++ pdb_set_nt_passwd(pass, NULL, PDB_SET); ++ } ++ } ++ ++ return; ++} ++ + NTSTATUS smb_register_passdb(int version, const char *name, pdb_init_function init) + { + struct pdb_init_function_entry *entry = backends; +@@ -141,6 +179,7 @@ + context->pwent_methods->setsampwent(context->pwent_methods, False); + } + user->methods = context->pwent_methods; ++ pdb_force_pw_initialization(user); + return ret; + } + +@@ -156,6 +195,7 @@ + curmethods = context->pdb_methods; + while (curmethods){ + if (NT_STATUS_IS_OK(ret = curmethods->getsampwnam(curmethods, sam_acct, username))) { ++ pdb_force_pw_initialization(sam_acct); + sam_acct->methods = curmethods; + return ret; + } +@@ -179,6 +219,7 @@ + + while (curmethods){ + if (NT_STATUS_IS_OK(ret = curmethods->getsampwsid(curmethods, sam_acct, sid))) { ++ pdb_force_pw_initialization(sam_acct); + sam_acct->methods = curmethods; + return ret; + } +@@ -191,12 +232,26 @@ + static NTSTATUS context_add_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct) + { + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; ++ const char *lm_pw, *nt_pw; ++ uint16 acb_flags; + + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + ++ /* disable acccounts with no passwords (that has not ++ been allowed by the ACB_PWNOTREQ bit */ ++ ++ lm_pw = pdb_get_lanman_passwd( sam_acct ); ++ nt_pw = pdb_get_lanman_passwd( sam_acct ); ++ acb_flags = pdb_get_acct_ctrl( sam_acct ); ++ if ( !lm_pw && !nt_pw && !(acb_flags&ACB_PWNOTREQ) ) { ++ acb_flags |= ACB_DISABLED; ++ pdb_set_acct_ctrl( sam_acct, acb_flags, PDB_SET ); ++ pdb_set_init_flags(sam_acct, PDB_ACCTCTRL, PDB_SET); ++ } ++ + /** @todo This is where a 're-read on add' should be done */ + /* We now add a new account to the first database listed. + * Should we? */ +@@ -207,6 +262,8 @@ + static NTSTATUS context_update_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct) + { + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; ++ const char *lm_pw, *nt_pw; ++ uint16 acb_flags; + + if (!context) { + DEBUG(0, ("invalid pdb_context specified!\n")); +@@ -218,6 +275,18 @@ + return ret; + } + ++ /* disable acccounts with no passwords (that has not ++ been allowed by the ACB_PWNOTREQ bit */ ++ ++ lm_pw = pdb_get_lanman_passwd( sam_acct ); ++ nt_pw = pdb_get_lanman_passwd( sam_acct ); ++ acb_flags = pdb_get_acct_ctrl( sam_acct ); ++ if ( !lm_pw && !nt_pw && !(acb_flags&ACB_PWNOTREQ) ) { ++ acb_flags |= ACB_DISABLED; ++ pdb_set_acct_ctrl( sam_acct, acb_flags, PDB_SET ); ++ pdb_set_init_flags(sam_acct, PDB_ACCTCTRL, PDB_SET); ++ } ++ + /** @todo This is where a 're-read on update' should be done */ + + return sam_acct->methods->update_sam_account(sam_acct->methods, sam_acct); +@@ -671,7 +740,7 @@ + if (!pdb_context) { + return False; + } +- ++ + return NT_STATUS_IS_OK(pdb_context->pdb_add_sam_account(pdb_context, sam_acct)); + } + +Index: source/utils/pdbedit.c +=================================================================== +RCS file: /data/cvs/samba/source/utils/pdbedit.c,v +retrieving revision 1.87.2.5 +diff -u -r1.87.2.5 pdbedit.c +--- utils/pdbedit.c 4 Dec 2003 20:35:40 -0000 1.87.2.5 ++++ utils/pdbedit.c 5 Feb 2004 14:43:54 -0000 +@@ -47,6 +47,7 @@ + #define BIT_RESERV_7 0x00800000 + #define BIT_IMPORT 0x01000000 + #define BIT_EXPORT 0x02000000 ++#define BIT_FIX_INIT 0x04000000 + + #define MASK_ALWAYS_GOOD 0x0000001F + #define MASK_USER_GOOD 0x00401F00 +@@ -234,6 +235,39 @@ + } + + /********************************************************* ++ Fix a list of Users for uninitialised passwords ++**********************************************************/ ++static int fix_users_list (struct pdb_context *in) ++{ ++ SAM_ACCOUNT *sam_pwent=NULL; ++ BOOL check, ret; ++ ++ check = NT_STATUS_IS_OK(in->pdb_setsampwent(in, False)); ++ if (!check) { ++ return 1; ++ } ++ ++ check = True; ++ if (!(NT_STATUS_IS_OK(pdb_init_sam(&sam_pwent)))) return 1; ++ ++ while (check && (ret = NT_STATUS_IS_OK(in->pdb_getsampwent (in, sam_pwent)))) { ++ if (!pdb_update_sam_account(sam_pwent)) { ++ DEBUG(0, ("Update of user %s failed!\n", pdb_get_username(sam_pwent))); ++ } ++ pdb_free_sam(&sam_pwent); ++ check = NT_STATUS_IS_OK(pdb_init_sam(&sam_pwent)); ++ if (!check) { ++ DEBUG(0, ("Failed to initialise new SAM_ACCOUNT structure (out of memory?)\n")); ++ } ++ ++ } ++ if (check) pdb_free_sam(&sam_pwent); ++ ++ in->pdb_endsampwent(in); ++ return 0; ++} ++ ++/********************************************************* + Set User Info + **********************************************************/ + +@@ -550,6 +584,7 @@ + static char *backend_in = NULL; + static char *backend_out = NULL; + static BOOL transfer_groups = False; ++ static BOOL force_initialised_password = False; + static char *logon_script = NULL; + static char *profile_path = NULL; + static char *account_control = NULL; +@@ -587,6 +622,7 @@ + {"account-policy", 'P', POPT_ARG_STRING, &account_policy, 0,"value of an account policy (like maximum password age)",NULL}, + {"value", 'C', POPT_ARG_LONG, &account_policy_value, 'C',"set the account policy to this value", NULL}, + {"account-control", 'c', POPT_ARG_STRING, &account_control, 0, "Values of account control", NULL}, ++ {"force-initialized-passwords", 0, POPT_ARG_NONE, &force_initialised_password, 0, "Force initialization of corrupt password strings in a passdb backend", NULL}, + POPT_COMMON_SAMBA + POPT_TABLEEND + }; +@@ -631,6 +667,7 @@ + (machine ? BIT_MACHINE : 0) + + (user_name ? BIT_USER : 0) + + (list_users ? BIT_LIST : 0) + ++ (force_initialised_password ? BIT_FIX_INIT : 0) + + (modify_user ? BIT_MODIFY : 0) + + (add_user ? BIT_CREATE : 0) + + (delete_user ? BIT_DELETE : 0) + +@@ -654,6 +691,10 @@ + + /* the lowest bit options are always accepted */ + checkparms = setparms & ~MASK_ALWAYS_GOOD; ++ ++ if (checkparms & BIT_FIX_INIT) { ++ return fix_users_list(bdef); ++ } + + /* account policy operations */ + if ((checkparms & BIT_ACCPOLICY) && !(checkparms & ~(BIT_ACCPOLICY + BIT_ACCPOLVAL))) { diff --git a/net/samba3/Makefile b/net/samba3/Makefile index ae18a40f317e..4e087ed2bb09 100644 --- a/net/samba3/Makefile +++ b/net/samba3/Makefile @@ -7,11 +7,11 @@ PORTNAME= samba PORTVERSION= 3.0.1 -PORTREVISION= 1 +PORTREVISION= 2 PORTEPOCH= 1 CATEGORIES= net MASTER_SITES= http://us3.samba.org/samba/ftp/%SUBDIR%/ -MASTER_SITE_SUBDIR= . rc +MASTER_SITE_SUBDIR= . rc old-versions #DISTNAME= ${PORTNAME}-${PORTVERSION:S/.r/rc/} MAINTAINER= dwcjr@FreeBSD.org diff --git a/net/samba3/files/patch-unit_pw b/net/samba3/files/patch-unit_pw new file mode 100644 index 000000000000..822010cb12e3 --- /dev/null +++ b/net/samba3/files/patch-unit_pw @@ -0,0 +1,263 @@ +Index: source/passdb/pdb_get_set.c +=================================================================== +RCS file: /data/cvs/samba/source/passdb/pdb_get_set.c,v +retrieving revision 1.26.2.4 +diff -u -r1.26.2.4 pdb_get_set.c +--- passdb/pdb_get_set.c 7 Nov 2003 17:36:50 -0000 1.26.2.4 ++++ passdb/pdb_get_set.c 5 Feb 2004 14:43:53 -0000 +@@ -933,7 +933,11 @@ + + data_blob_clear_free(&sampass->private.nt_pw); + +- sampass->private.nt_pw = data_blob(pwd, NT_HASH_LEN); ++ if (pwd) { ++ sampass->private.nt_pw = data_blob(pwd, NT_HASH_LEN); ++ } else { ++ sampass->private.nt_pw = data_blob(NULL, 0); ++ } + + return pdb_set_init_flags(sampass, PDB_NTPASSWD, flag); + } +@@ -949,7 +953,11 @@ + + data_blob_clear_free(&sampass->private.lm_pw); + +- sampass->private.lm_pw = data_blob(pwd, LM_HASH_LEN); ++ if (pwd) { ++ sampass->private.lm_pw = data_blob(pwd, LM_HASH_LEN); ++ } else { ++ sampass->private.lm_pw = data_blob(NULL, 0); ++ } + + return pdb_set_init_flags(sampass, PDB_LMPASSWD, flag); + } +Index: source/passdb/pdb_interface.c +=================================================================== +RCS file: /data/cvs/samba/source/passdb/pdb_interface.c,v +retrieving revision 1.47.2.3 +diff -u -r1.47.2.3 pdb_interface.c +--- passdb/pdb_interface.c 8 Sep 2003 14:13:34 -0000 1.47.2.3 ++++ passdb/pdb_interface.c 5 Feb 2004 14:43:54 -0000 +@@ -36,6 +36,44 @@ + + static struct pdb_init_function_entry *pdb_find_backend_entry(const char *name); + ++/******************************************************************* ++ Clean up uninitialised passwords. The only way to tell ++ that these values are not 'real' is that they do not ++ have a valid last set time. Instead, the value is fixed at 0. ++ Therefore we use that as the key for 'is this a valid password'. ++ However, it is perfectly valid to have a 'default' last change ++ time, such LDAP with a missing attribute would produce. ++********************************************************************/ ++ ++static void pdb_force_pw_initialization(SAM_ACCOUNT *pass) ++{ ++ const char *lm_pwd, *nt_pwd; ++ ++ /* only reset a password if the last set time has been ++ explicitly been set to zero. A default last set time ++ is ignored */ ++ ++ if ( (pdb_get_init_flags(pass, PDB_PASSLASTSET) != PDB_DEFAULT) ++ && (pdb_get_pass_last_set_time(pass) == 0) ) ++ { ++ ++ if (pdb_get_init_flags(pass, PDB_LMPASSWD) != PDB_DEFAULT) ++ { ++ lm_pwd = pdb_get_lanman_passwd(pass); ++ if (lm_pwd) ++ pdb_set_lanman_passwd(pass, NULL, PDB_SET); ++ } ++ if (pdb_get_init_flags(pass, PDB_NTPASSWD) != PDB_DEFAULT) ++ { ++ nt_pwd = pdb_get_nt_passwd(pass); ++ if (nt_pwd) ++ pdb_set_nt_passwd(pass, NULL, PDB_SET); ++ } ++ } ++ ++ return; ++} ++ + NTSTATUS smb_register_passdb(int version, const char *name, pdb_init_function init) + { + struct pdb_init_function_entry *entry = backends; +@@ -141,6 +179,7 @@ + context->pwent_methods->setsampwent(context->pwent_methods, False); + } + user->methods = context->pwent_methods; ++ pdb_force_pw_initialization(user); + return ret; + } + +@@ -156,6 +195,7 @@ + curmethods = context->pdb_methods; + while (curmethods){ + if (NT_STATUS_IS_OK(ret = curmethods->getsampwnam(curmethods, sam_acct, username))) { ++ pdb_force_pw_initialization(sam_acct); + sam_acct->methods = curmethods; + return ret; + } +@@ -179,6 +219,7 @@ + + while (curmethods){ + if (NT_STATUS_IS_OK(ret = curmethods->getsampwsid(curmethods, sam_acct, sid))) { ++ pdb_force_pw_initialization(sam_acct); + sam_acct->methods = curmethods; + return ret; + } +@@ -191,12 +232,26 @@ + static NTSTATUS context_add_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct) + { + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; ++ const char *lm_pw, *nt_pw; ++ uint16 acb_flags; + + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + ++ /* disable acccounts with no passwords (that has not ++ been allowed by the ACB_PWNOTREQ bit */ ++ ++ lm_pw = pdb_get_lanman_passwd( sam_acct ); ++ nt_pw = pdb_get_lanman_passwd( sam_acct ); ++ acb_flags = pdb_get_acct_ctrl( sam_acct ); ++ if ( !lm_pw && !nt_pw && !(acb_flags&ACB_PWNOTREQ) ) { ++ acb_flags |= ACB_DISABLED; ++ pdb_set_acct_ctrl( sam_acct, acb_flags, PDB_SET ); ++ pdb_set_init_flags(sam_acct, PDB_ACCTCTRL, PDB_SET); ++ } ++ + /** @todo This is where a 're-read on add' should be done */ + /* We now add a new account to the first database listed. + * Should we? */ +@@ -207,6 +262,8 @@ + static NTSTATUS context_update_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct) + { + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; ++ const char *lm_pw, *nt_pw; ++ uint16 acb_flags; + + if (!context) { + DEBUG(0, ("invalid pdb_context specified!\n")); +@@ -218,6 +275,18 @@ + return ret; + } + ++ /* disable acccounts with no passwords (that has not ++ been allowed by the ACB_PWNOTREQ bit */ ++ ++ lm_pw = pdb_get_lanman_passwd( sam_acct ); ++ nt_pw = pdb_get_lanman_passwd( sam_acct ); ++ acb_flags = pdb_get_acct_ctrl( sam_acct ); ++ if ( !lm_pw && !nt_pw && !(acb_flags&ACB_PWNOTREQ) ) { ++ acb_flags |= ACB_DISABLED; ++ pdb_set_acct_ctrl( sam_acct, acb_flags, PDB_SET ); ++ pdb_set_init_flags(sam_acct, PDB_ACCTCTRL, PDB_SET); ++ } ++ + /** @todo This is where a 're-read on update' should be done */ + + return sam_acct->methods->update_sam_account(sam_acct->methods, sam_acct); +@@ -671,7 +740,7 @@ + if (!pdb_context) { + return False; + } +- ++ + return NT_STATUS_IS_OK(pdb_context->pdb_add_sam_account(pdb_context, sam_acct)); + } + +Index: source/utils/pdbedit.c +=================================================================== +RCS file: /data/cvs/samba/source/utils/pdbedit.c,v +retrieving revision 1.87.2.5 +diff -u -r1.87.2.5 pdbedit.c +--- utils/pdbedit.c 4 Dec 2003 20:35:40 -0000 1.87.2.5 ++++ utils/pdbedit.c 5 Feb 2004 14:43:54 -0000 +@@ -47,6 +47,7 @@ + #define BIT_RESERV_7 0x00800000 + #define BIT_IMPORT 0x01000000 + #define BIT_EXPORT 0x02000000 ++#define BIT_FIX_INIT 0x04000000 + + #define MASK_ALWAYS_GOOD 0x0000001F + #define MASK_USER_GOOD 0x00401F00 +@@ -234,6 +235,39 @@ + } + + /********************************************************* ++ Fix a list of Users for uninitialised passwords ++**********************************************************/ ++static int fix_users_list (struct pdb_context *in) ++{ ++ SAM_ACCOUNT *sam_pwent=NULL; ++ BOOL check, ret; ++ ++ check = NT_STATUS_IS_OK(in->pdb_setsampwent(in, False)); ++ if (!check) { ++ return 1; ++ } ++ ++ check = True; ++ if (!(NT_STATUS_IS_OK(pdb_init_sam(&sam_pwent)))) return 1; ++ ++ while (check && (ret = NT_STATUS_IS_OK(in->pdb_getsampwent (in, sam_pwent)))) { ++ if (!pdb_update_sam_account(sam_pwent)) { ++ DEBUG(0, ("Update of user %s failed!\n", pdb_get_username(sam_pwent))); ++ } ++ pdb_free_sam(&sam_pwent); ++ check = NT_STATUS_IS_OK(pdb_init_sam(&sam_pwent)); ++ if (!check) { ++ DEBUG(0, ("Failed to initialise new SAM_ACCOUNT structure (out of memory?)\n")); ++ } ++ ++ } ++ if (check) pdb_free_sam(&sam_pwent); ++ ++ in->pdb_endsampwent(in); ++ return 0; ++} ++ ++/********************************************************* + Set User Info + **********************************************************/ + +@@ -550,6 +584,7 @@ + static char *backend_in = NULL; + static char *backend_out = NULL; + static BOOL transfer_groups = False; ++ static BOOL force_initialised_password = False; + static char *logon_script = NULL; + static char *profile_path = NULL; + static char *account_control = NULL; +@@ -587,6 +622,7 @@ + {"account-policy", 'P', POPT_ARG_STRING, &account_policy, 0,"value of an account policy (like maximum password age)",NULL}, + {"value", 'C', POPT_ARG_LONG, &account_policy_value, 'C',"set the account policy to this value", NULL}, + {"account-control", 'c', POPT_ARG_STRING, &account_control, 0, "Values of account control", NULL}, ++ {"force-initialized-passwords", 0, POPT_ARG_NONE, &force_initialised_password, 0, "Force initialization of corrupt password strings in a passdb backend", NULL}, + POPT_COMMON_SAMBA + POPT_TABLEEND + }; +@@ -631,6 +667,7 @@ + (machine ? BIT_MACHINE : 0) + + (user_name ? BIT_USER : 0) + + (list_users ? BIT_LIST : 0) + ++ (force_initialised_password ? BIT_FIX_INIT : 0) + + (modify_user ? BIT_MODIFY : 0) + + (add_user ? BIT_CREATE : 0) + + (delete_user ? BIT_DELETE : 0) + +@@ -654,6 +691,10 @@ + + /* the lowest bit options are always accepted */ + checkparms = setparms & ~MASK_ALWAYS_GOOD; ++ ++ if (checkparms & BIT_FIX_INIT) { ++ return fix_users_list(bdef); ++ } + + /* account policy operations */ + if ((checkparms & BIT_ACCPOLICY) && !(checkparms & ~(BIT_ACCPOLICY + BIT_ACCPOLVAL))) {