[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