[Samba] Securty hole (to Jeremy Allison):password chat
Mathias.Wohlfarth at mw-eb.de
Mathias.Wohlfarth at mw-eb.de
Tue Nov 30 11:40:29 GMT 2004
As you ar looking for security holes:
With password chat it is easy to exchange the change password program and
log to users passwords. Because on AIX password chat does not work we have
implemented the unix password change with system calls directly from the
samba code. We have a new parameter to switch this option on. It takes
effect when unix password sync is yes. In this case password chat is never
reached. The code is running with Samba 2.2.2 and 2.2.8 on AIX (80
locations each with about 80 to 300 users). I am going to implement this
in 3.0.8 or 9 which will be our next production release. The code also has
been tested with Linux, but only with few users.
I have added the code and would be glad if you think it is worth to be
implemented in a next release.
regards Mathias
ADD TO include/includes.h
#include <userpw.h>
#include <usersec.h>
__________________________________________________________________________
ADD TO param/loadparm.c
BOOL bDirectPasswdSync;
Globals.bDirectPasswdSync = False;
FN_GLOBAL_BOOL(lp_direct_password_sync, &Globals.bDirectPasswdSync)
__________________________________________________________________________
ADD TO smbd/chgpasswd.c
@@ -521,6 +542,43 @@
return ret;
}
#endif
+/********************************************************************/
+/* ADDSTART security enhancement Mathias.Wohlfarth at m-wohlfarth.de */
+/********************************************************************/
+ if (lp_direct_password_sync()) {
+ status = direct_password_sync(name,newpass,as_root);
+ if (!NT_STATUS_IS_OK(status)) {
+ /* we lose status here */
+ /* confusing for the user - password is changed!
*/
+ return False;
+ }
+ return True; /* forget the rest */
+ }
___________________________________________________________________________
ADD NEW FUNCTION
#include "includes.h"
NTSTATUS direct_password_sync(const char *name,const char *newpass,BOOL
as_root)
{
char salt[3];
#ifdef AIX
#define PASSWD userpw
#define GETPWNAM getuserpw
#define PW_PASSWD upw_passwd
#else /* tested on Linux */
#define PASSWD passwd
#define GETPWNAM getpwnam
#define PW_PASSWD pw_passwd
#endif
struct PASSWD *PASSWD;
char *alpha =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890./";
if (as_root) become_root();
#ifdef AIX
setpwdb(S_READ | S_WRITE); /* only AIX */
#endif
if (! (PASSWD = GETPWNAM(name))) {
DEBUG(0,
("Password Change: user %s unknown on operating
system.\n",
name));
#ifdef AIX
endpwdb(); /* only for AIX */
#endif
if (as_root) unbecome_root();
return NT_STATUS_INTERNAL_ERROR;
}
salt[0] = alpha[time(NULL) % strlen(alpha)];
salt[1] = alpha[getpid() % strlen(alpha)];
salt[2] = 0;
PASSWD->PW_PASSWD = crypt(newpass,salt);
#ifdef AIX
userpw->upw_lastupdate = time(NULL);
if (putuserpw(userpw)) {
DEBUG(0,
("Password Change: could not change password for
user %s on operating system.\n",
name));
endpwdb();
if (as_root) unbecome_root();
return NT_STATUS_INTERNAL_ERROR;
}
endpwdb();
#else /* not AIX tested on Linux */
/* I like AIX */
#define PASSWD_MODE 0644
{
FILE* tmp_file;
FILE* sav_file;
pstring passwd_name = "/etc/passwd";
pstring passwd_name_tmp = "/etc/passwd.smbd.tmp";
pstring passwd_name_sav = "/etc/opasswd.smbd";
struct passwd *passwd_tmp;
tmp_file = sys_fopen(passwd_name_tmp,"w");
if (tmp_file == NULL) {
DEBUG(0,
("Password Change: could not open %s (user:%s)",
passwd_name_tmp,name));
if (as_root) unbecome_root();
return NT_STATUS_INTERNAL_ERROR;
}
sav_file = sys_fopen(passwd_name_sav,"w");
if (tmp_file == NULL) {
DEBUG(0,
("Password Change: could not open %s (user:%s)",
passwd_name_sav,name));
if (as_root) unbecome_root();
return NT_STATUS_INTERNAL_ERROR;
}
setpwent();
while ((passwd_tmp = getpwent()) != NULL) {
if (strcmp(passwd_tmp->pw_name, PASSWD->pw_name) == 0) {
if (putpwent(PASSWD,tmp_file) != 0) {
DEBUG(0,
("Password Change: could not putpwent
%s
(user:%s)",
passwd_name_tmp,name));
endpwent();
if (as_root) unbecome_root();
return NT_STATUS_INTERNAL_ERROR
;
}
}
else {
if (putpwent(passwd_tmp,tmp_file) != 0) {
DEBUG(0,
("Password Change: could not putpwent
%s
(user:%s)",
passwd_name_tmp,name));
endpwent();
if (as_root) unbecome_root();
return NT_STATUS_INTERNAL_ERROR;
}
}
if (putpwent(passwd_tmp, sav_file) != 0) {
DEBUG(0,
("Password Change: could not putpwent %s
(user:%s)",
passwd_name_sav,name));
endpwent();
if (as_root) unbecome_root();
return NT_STATUS_INTERNAL_ERROR;
}
}
if (fclose(tmp_file) != 0) {
DEBUG(0,
("Password Change: could not putpwent %s (user:%s)",
passwd_name_tmp,name));
endpwent();
if (as_root) unbecome_root();
return NT_STATUS_INTERNAL_ERROR;
}
if (fclose(sav_file) != 0) {
DEBUG(0,
("Password Change: could not putpwent %s (user:%s)",
passwd_name_sav,name));
endpwent();
if (as_root) unbecome_root();
return NT_STATUS_INTERNAL_ERROR;
}
endpwent();
chmod(passwd_name_sav,0644);
chmod(passwd_name_tmp,0644);
if (rename(passwd_name_tmp, passwd_name) != 0) {
DEBUG(0,
("Password Change: could not rename %s to %s
(user:%s)",
passwd_name_tmp,passwd_name,name));
endpwent();
if (as_root) unbecome_root();
return NT_STATUS_INTERNAL_ERROR;
}
}
#endif /* not AIX */
/* all together now */
DEBUG(0,
("Password Change: changed password for user %s on operating
system.\n",
name));
if (as_root) unbecome_root();
return NT_STATUS_OK; /* forget the rest */
}
More information about the samba
mailing list