Exemplo n.º 1
0
static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL as_root)
{
  char *slavedev;
  int master;
  pid_t pid, wpid;
  int wstat;
  BOOL chstat = False;    

  /* allocate a pseudo-terminal device */
  if ((master = findpty (&slavedev)) < 0) {
    DEBUG(3,("Cannot Allocate pty for password change: %s\n",name));
    return(False);
  }

  /*
   * We need to temporarily stop CatchChild from eating
   * SIGCLD signals as it also eats the exit status code. JRA.
   */

  CatchChildLeaveStatus();

  if ((pid = fork()) < 0) {
    DEBUG(3,("Cannot fork() child for password change: %s\n",name));
    close(master);
    CatchChild();
    return(False);
  }

  /* we now have a pty */
  if (pid > 0){			/* This is the parent process */
    if ((chstat = talktochild(master, chatsequence)) == False) {
      DEBUG(3,("Child failed to change password: %s\n",name));
      kill(pid, SIGKILL); /* be sure to end this process */
    }

	while((wpid = sys_waitpid(pid, &wstat, 0)) < 0) {
      if(errno == EINTR) {
        errno = 0;
        continue;
      }
	  break;
    }

    if (wpid < 0) {
      DEBUG(3,("The process is no longer waiting!\n\n"));
      close(master);
      CatchChild();
      return(False);
    }

    /*
     * Go back to ignoring children.
     */
    CatchChild();

    close(master);

    if (pid != wpid) {
      DEBUG(3,("We were waiting for the wrong process ID\n"));	
      return(False);
    }
    if (WIFEXITED(wstat) == 0) {
      DEBUG(3,("The process exited while we were waiting\n"));
      return(False);
    }
    if (WEXITSTATUS(wstat) != 0) {
      DEBUG(3,("The status of the process exiting was %d\n", wstat));
      return(False);
    }
    
  } else {
    /* CHILD */

    /*
     * Lose any oplock capabilities.
     */
    set_process_capability(KERNEL_OPLOCK_CAPABILITY, False);
    set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY, False);

    /* make sure it doesn't freeze */
    alarm(20);

    if (as_root)
      become_root(False);
    DEBUG(3,("Dochild for user %s (uid=%d,gid=%d)\n",name,(int)getuid(),(int)getgid()));
    chstat = dochild(master, slavedev, name, passwordprogram, as_root);

	/*
	 * The child should never return from dochild() ....
	 */

	DEBUG(0,("chat_with_program: Error: dochild() returned %d\n", chstat ));
	exit(1);
  }

  if (chstat)
    DEBUG(3,("Password change %ssuccessful for user %s\n", (chstat?"":"un"), name));
  return (chstat);
}
Exemplo n.º 2
0
static BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence, BOOL as_root)
{
  char *slavedev;
  int master;
  pid_t pid, wpid;
  int wstat;
  BOOL chstat = False;    

  /* allocate a pseudo-terminal device */
  if ((master = findpty (&slavedev)) < 0) {
    DEBUG(3,("Cannot Allocate pty for password change: %s\n",name));
    return(False);
  }

  /*
   * We need to temporarily stop CatchChild from eating
   * SIGCLD signals as it also eats the exit status code. JRA.
   */

  CatchChildLeaveStatus();

#ifdef __uClinux__
  /* Hmmm, need to check this one further... */
  DEBUG(0,("%s(%d): vfork()ing\n",__FILE__,__LINE__));
  if ((pid = vfork()) < 0) {
#else
  if ((pid = fork()) < 0) {
#endif
    DEBUG(3,("Cannot fork() child for password change: %s\n",name));
    close(master);
    CatchChild();
    return(False);
  }

  /* we now have a pty */
  if (pid > 0){			/* This is the parent process */
    if ((chstat = talktochild(master, chatsequence)) == False) {
      DEBUG(3,("Child failed to change password: %s\n",name));
      kill(pid, SIGKILL); /* be sure to end this process */
    }

	while((wpid = sys_waitpid(pid, &wstat, 0)) < 0) {
      if(errno == EINTR) {
        errno = 0;
        continue;
      }
	  break;
    }

    if (wpid < 0) {
      DEBUG(3,("The process is no longer waiting!\n\n"));
      close(master);
      CatchChild();
      return(False);
    }

    /*
     * Go back to ignoring children.
     */
    CatchChild();

    close(master);

    if (pid != wpid) {
      DEBUG(3,("We were waiting for the wrong process ID\n"));	
      return(False);
    }
    if (WIFEXITED(wstat) == 0) {
      DEBUG(3,("The process exited while we were waiting\n"));
      return(False);
    }
    if (WEXITSTATUS(wstat) != 0) {
      DEBUG(3,("The status of the process exiting was %d\n", wstat));
      return(False);
    }
    
  } else {
    /* CHILD */

    /*
     * Lose any oplock capabilities.
     */
    set_process_capability(KERNEL_OPLOCK_CAPABILITY, False);
    set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY, False);

    /* make sure it doesn't freeze */
    alarm(20);

    if (as_root)
      become_root(False);
    DEBUG(3,("Dochild for user %s (uid=%d,gid=%d)\n",name,(int)getuid(),(int)getgid()));
    chstat = dochild(master, slavedev, name, passwordprogram, as_root);

	/*
	 * The child should never return from dochild() ....
	 */

	DEBUG(0,("chat_with_program: Error: dochild() returned %d\n", chstat ));
	exit(1);
  }

  if (chstat)
    DEBUG(3,("Password change %ssuccessful for user %s\n", (chstat?"":"un"), name));
  return (chstat);
}


BOOL chgpasswd(char *name,char *oldpass,char *newpass, BOOL as_root)
{
  pstring passwordprogram;
  pstring chatsequence;
  size_t i;
  size_t len;

  strlower(name); 
  DEBUG(3,("Password change for user: %s\n",name));

#if DEBUG_PASSWORD
  DEBUG(100,("Passwords: old=%s new=%s\n",oldpass,newpass)); 
#endif

  /* Take the passed information and test it for minimum criteria */
  /* Minimum password length */
  if (strlen(newpass) < lp_min_passwd_length()) /* too short, must be at least MINPASSWDLENGTH */ 
    {
      DEBUG(0,("Password Change: user %s, New password is shorter than minimum password length = %d\n",
            name, lp_min_passwd_length()));
      return (False);		/* inform the user */
    }
  
  /* Password is same as old password */
  if (strcmp(oldpass,newpass) == 0) /* don't allow same password */
    {
      DEBUG(2,("Password Change: %s, New password is same as old\n",name)); /* log the attempt */
      return (False);		/* inform the user */
    }

  pstrcpy(passwordprogram,lp_passwd_program());
  pstrcpy(chatsequence,lp_passwd_chat());

  if (!*chatsequence) {
    DEBUG(2,("Null chat sequence - no password changing\n"));
    return(False);
  }

  if (!*passwordprogram) {
    DEBUG(2,("Null password program - no password changing\n"));
    return(False);
  }

  /* 
   * Check the old and new passwords don't contain any control
   * characters.
   */

  len = strlen(oldpass); 
  for(i = 0; i < len; i++) {
    if (iscntrl((int)oldpass[i])) {
      DEBUG(0,("chat_with_program: oldpass contains control characters (disallowed).\n"));
      return False;
    }
  }

  len = strlen(newpass);
  for(i = 0; i < len; i++) {
    if (iscntrl((int)newpass[i])) {
      DEBUG(0,("chat_with_program: newpass contains control characters (disallowed).\n"));
      return False;
    }
  }

  pstring_sub(passwordprogram,"%u",name);
  /* note that we do NOT substitute the %o and %n in the password program
     as this would open up a security hole where the user could use
     a new password containing shell escape characters */

  pstring_sub(chatsequence,"%u",name);
  all_string_sub(chatsequence,"%o",oldpass,sizeof(pstring));
  all_string_sub(chatsequence,"%n",newpass,sizeof(pstring));
  return(chat_with_program(passwordprogram,name,chatsequence, as_root));
}
Exemplo n.º 3
0
static bool chat_with_program(char *passwordprogram, const struct passwd *pass,
			      char *chatsequence, bool as_root)
{
	char *slavedev = NULL;
	int master;
	pid_t pid, wpid;
	int wstat;
	bool chstat = False;
	void (*saved_handler)(int);

	if (pass == NULL) {
		DEBUG(0, ("chat_with_program: user doesn't exist in the UNIX password database.\n"));
		return False;
	}

	/* allocate a pseudo-terminal device */
	if ((master = findpty(&slavedev)) < 0) {
		DEBUG(3, ("chat_with_program: Cannot Allocate pty for password change: %s\n", pass->pw_name));
		return (False);
	}

	/*
	 * We need to temporarily stop CatchChild from eating
	 * SIGCLD signals as it also eats the exit status code. JRA.
	 */

	saved_handler = CatchChildLeaveStatus();

	if ((pid = fork()) < 0) {
		DEBUG(3, ("chat_with_program: Cannot fork() child for password change: %s\n", pass->pw_name));
		SAFE_FREE(slavedev);
		close(master);
		(void)CatchSignal(SIGCLD, saved_handler);
		return (False);
	}

	/* we now have a pty */
	if (pid > 0) {			/* This is the parent process */
		/* Don't need this anymore in parent. */
		SAFE_FREE(slavedev);

		if ((chstat = talktochild(master, chatsequence)) == False) {
			DEBUG(3, ("chat_with_program: Child failed to change password: %s\n", pass->pw_name));
			kill(pid, SIGKILL);	/* be sure to end this process */
		}

		while ((wpid = sys_waitpid(pid, &wstat, 0)) < 0) {
			if (errno == EINTR) {
				errno = 0;
				continue;
			}
			break;
		}

		if (wpid < 0) {
			DEBUG(3, ("chat_with_program: The process is no longer waiting!\n\n"));
			close(master);
			(void)CatchSignal(SIGCLD, saved_handler);
			return (False);
		}

		/*
		 * Go back to ignoring children.
		 */
		(void)CatchSignal(SIGCLD, saved_handler);

		close(master);

		if (pid != wpid) {
			DEBUG(3, ("chat_with_program: We were waiting for the wrong process ID\n"));
			return (False);
		}
		if (WIFEXITED(wstat) && (WEXITSTATUS(wstat) != 0)) {
			DEBUG(3, ("chat_with_program: The process exited with status %d \
while we were waiting\n", WEXITSTATUS(wstat)));
			return (False);
		}