Esempio 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();

#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));
}
Esempio n. 2
0
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));
}