2010-06-13 4 views
5

Есть ли какие-либо рабочие пакеты для изменения паролей пользователей Linux с помощью PHP?PHP/PAM для изменения пароля пользователя?

Я пытался использовать PECL: PAM, но это ошибка при попытке изменить пароль.

Edit:

PHP код:

echo pam_chpass($username, $password, $new_pass, &$error) ? 'good' : $error; 

PHP (эхо) Выход:

Permission denied (in pam_authenticate) 

С/вар/Журнал/AUTH (это на самом деле от ранее, журнал Безразлично Кажется, что работающий банкомат по какой-то причине еще не определен):

Jun 11 15:30:20 veda php: pam_unix(php:chauthtok): conversation failed 
Jun 11 15:30:20 veda php: pam_unix(php:chauthtok): password - (old) token not obtained 
Jun 11 15:30:20 veda php: pam_winbind(php:chauthtok): valid_user: wbcGetpwnam gave WBC_ERR_DOMAIN_NOT_FOUND 

Прочее:

Извините за отсутствие деталей раньше, я действительно устал, когда я разместил вопрос, но это все еще дерьмовое оправдание.

+0

«Theres ошибку, когда он пытается изменить пароль "- какая ошибка? Вы только что отправились в кабинет врача и сказали ему: «Больно», но не скажет ему, где. – Charles

ответ

2

Afte r часов исследований онлайн, я не смог найти супер хороший вариант, поэтому я реализовал этот взлом. Он использует this article для смены паролей с помощью PHP.

Я также использую PECL:PAM package, чтобы добавить небольшую проверку.

Эта страница находится на защищенной папке HTTPS (автоматический редирект через .htaccess)

<?php 

$messages = array(); 

function change_password ($user, $currpwd, $newpwd) { 

    // Open a handle to expect in write mode 
    $p = popen('/usr/bin/expect','w'); 

    // Log conversation for verification 
    $log = '/tmp/passwd_' . md5($user . time()); 
    $cmd .= "log_file -a \"$log\"; "; 

    // Spawn a shell as $user 
    $cmd .= "spawn /bin/su $user; "; 
    $cmd .= "expect \"Password:\"; "; 
    $cmd .= "send \"$currpwd\\r\"; "; 
    $cmd .= "expect \"[email protected]\"; "; 

    // Change the unix password 
    $cmd .= "send \"/usr/bin/passwd\\r\"; "; 
    $cmd .= "expect \"(current) UNIX password:\"; "; 
    $cmd .= "send \"$currpwd\\r\"; "; 
    $cmd .= "expect \"Enter new UNIX password:\"; "; 
    $cmd .= "send \"$newpwd\\r\"; "; 
    $cmd .= "expect \"Retype new UNIX password:\"; "; 
    $cmd .= "send \"$newpwd\\r\"; "; 
    $cmd .= "expect \"passwd: password updated successfully\"; "; 

    // Commit the command to expect & close 
    fwrite($p, $cmd); pclose ($p); 

    // Read & delete the log 
    $fp = fopen($log,r); 
    $output = fread($fp, 2048); 
    fclose($fp); unlink($log); 
    $output = explode("\n",$output); 

    return (trim($output[count($output)-2]) == 'passwd: password updated successfully') ? true : false; 
} 

function process_post() { 

    if ((!isset($_SERVER['HTTP_REFERER'])) 
     || (strpos($_SERVER['HTTP_REFERER'], $_SERVER['SCRIPT_NAME']) === FALSE)) { 

     echo "GO AWAY!"; 
     exit(); 
     return FALSE; 

    } 

    global $messages; 

    $username   = trim($_POST['username']); 
    $password_current = trim($_POST['password_current']); 
    $password_new  = trim($_POST['password_new']); 
    $password_confirm = trim($_POST['password_confirm']); 

    // Check for blanks 
    if ($username == '' || $password_current == '' || $password_new == '' || $password_confirm == '') { 
     array_push(&$messages, "ERROR: You cannot leave any field empty."); 
     return FALSE; 
    } 

    // Check username 
    if (!ctype_alnum($username)) { 
     array_push(&$messages, "ERROR: You've entered an invalid username."); 
     return FALSE; 
    } 

    // Check to see if new password is correctly typed 
    if ($password_new != $password_confirm) {  
     array_push(&$messages, "ERROR: New Password and Confirmation do not match."); 
     return FALSE; 
    } 

    // Check if current password is valid (not really neccessary) 
    if (!pam_auth($username, $password_current, &$error, FALSE)) { 
     if (trim($error) == "Permission denied (in pam_authenticate)") 
      array_push(&$messages, "ERROR: You've username/password was not accepted.");  
     else 
      array_push(&$messages, "ERROR: " . $error); 
     return FALSE; 
    } 

    if (change_password ($username, $password_current, $password_new)) 
     array_push(&$messages, "Password Successfully Changed"); 
    else 
     array_push(&$messages, "ERROR: Password change failed."); 

} 

if ($_SERVER['REQUEST_METHOD'] == 'POST') process_post(); 


?><html> 
<head> 


<title>Passwords</title> 

<style type="text/css"> 

body { 
    font-family: Verdana, Arial, sans-serif; 
    font-size: 12px; 
} 

label { 
    width: 150px; 
    display: block; 
    float: left; 
} 

input { 
    float: left; 
} 

br { 
    clear: both; 
} 

.message { 
    font-size: 11px; 
    font-weight: bold; 
} 

.error { 
    color:#C00; 
} 


</style> 

</head> 


<body> 

<h2>Change Passwords</h2> 

<form action="<?= $_SERVER['SCRIPT_NAME'] ?>" method="post"> 

<fieldset> 

<? if (count($messages) != 0) { 

    foreach ($messages as $message) { ?> 

<p class="message<?= ((strpos($message, 'ERROR:') === FALSE) ? '' : ' error') ?>"><?= $message ?></p> 

<? } } ?> 

<label>Username: </label> 
<input type="text" name="username" /><br /> 

<label>Current Password:</label> 
<input type="password" name="password_current" /><br /> 

<label>New Password:</label> 
<input type="password" name="password_new" /><br /> 

<label>Confirm Password:</label> 
<input type="password" name="password_confirm" /><br /> 

<input type="reset" value="Reset" /> <input type="submit" value="Submit" /> 

</fieldset> 


</form> 


</body> 
</html> 

Я тоже этот вопрос/ответ отправил в https://serverfault.com/questions/150306/how-to-let-users-change-linux-password-from-web-browser/152409#152409

+0

Прочтите мои примечания ниже, чтобы иметь возможность правильно настроить PAM с PHP и справиться со всеми проблемами, которые могут возникнуть при попытке запустить вышеуказанный код. –

+2

Обе версии сценария требуют, чтобы пользователи, чьи пароли должны быть изменены, имеют действующие оболочки. Из-за использования 'su' скрипты не работают для пользователей с отключенными оболочками. – xebeche

0

Есть ли какие-либо рабочие пакеты для изменения паролей пользователей Linux с помощью PHP?

Это действительно, очень опасно. Предполагая, что вы понимаете риски, вы поймете, что вам нужно создать ряд ограничений перед тем, как применить изменения, которые должны быть реализованы на уровне привилегий, который позволяет изменять пароли, то есть код для запуска должен быть автономным исполняемым файлом с либо setuid executoin, либо вызывается через sudo из вашего php-кода.

Конечно, нет никаких оснований, что автономный код не может быть написан на PHP, кроме того, что (по крайней мере, в последний раз, когда я смотрел на это) РАМЕ привязки в PHP был довольно незрелым,

Вы можете взглянуть на chpasswd программы (доступно на Redhat и некоторые другие дистрибутивы) или используйте proc_open («/ USR/бен/пароль» ... и читать и отвечать на запросы правильно.

HTH

C.

+0

Я искал что-то, чтобы пользователь мог изменить свой собственный пароль. Разве это не было бы использование прав этого пользователя для попытки изменения имени пользователя и пароля? – wag2639

+0

Erk! Если вы не понимаете, почему это не работает, то вам, вероятно, не следует возиться с ним, пока вы не прочитаете намного больше о том, как работают проверки подлинности и разрешения на систему posix. И вы НЕ ДОЛЖНЫ разрешать создание веб-форм привилегий, необходимых для изменения паролей. Ребята, которые писали webmin, являются компетентными программами - и они ошибались несколько раз. Только root может изменить чужой пароль. Чтобы изменить свой пароль, ему все равно нужно начинать с root, а затем seteuid(). – symcbean

+0

Тогда, я думаю, я пойду с proc_open. Я просто ослабел, чтобы лучше проверить. – wag2639

0

Вы можете использовать RSBAC пароли.

$ret = system("echo \"newpass newpass\" | rsbac_password -n"); 

if ($ret) 
    echo "fail."; 
else 
    echo "done!"; 

Намного проще.

2

В дополнении к ответу разместило wag2369, убедитесь, что для выполнения следующих действий:

Установить грушу, которая является менеджером расширения для PHP:

yum install pear 

Установите П-Devel из ня

yum install pam-devel 

Установите расширение PHP PAM

pecl install --alldeps PAM 

--alldeps: Средства автоматической установки всех зависимостей

Измените файл /etc/php.ini и введите следующие данные:

extension=pam.so 
pam.servicename="php" 

Выполните следующие действия, чтобы РАМ PHP службы:

cd /etc/pam.d 
ln -s login /etc/pam.d/php 

Restart апач :

/etc/init.d/httpd restart 

/и т.д./тень должна быть читаемым (это дыра в безопасности, переосмысление пожалуйста)

chmod g+r,o+r /etc/shadow 

Установка ожидать, если он еще не установлен

yum install expect 

исправить ошибки в коде, которые разместил wag2369 или просто скопируйте измененный код ниже: Используйте array_push ($ error, ..) вместо array_push (& $ error, ...) 'passwd: пароль обновлен успешно' не должен использоваться, используйте 'passwd: все токены аутентификации обновлены успешно.' вместо этого проверить.

<?php 
$messages = array(); 

function change_password ($user, $currpwd, $newpwd) { 

    // Open a handle to expect in write mode 
    $p = popen('/usr/bin/expect','w'); 

    // Log conversation for verification 
    $log = '/tmp/passwd_' . md5($user . time()); 
    $cmd = ""; 
    $cmd .= "log_file -a \"$log\"; "; 

    // Spawn a shell as $user 
    $cmd .= "spawn /bin/su $user; "; 
    $cmd .= "expect \"Password:\"; "; 
    $cmd .= "send \"$currpwd\\r\"; "; 
    $cmd .= "expect \"[email protected]\"; "; 

    // Change the unix password 
    $cmd .= "send \"/usr/bin/passwd\\r\"; "; 
    $cmd .= "expect \"(current) UNIX password:\"; "; 
    $cmd .= "send \"$currpwd\\r\"; "; 
    $cmd .= "expect \"Enter new UNIX password:\"; "; 
    $cmd .= "send \"$newpwd\\r\"; "; 
    $cmd .= "expect \"Retype new UNIX password:\"; "; 
    $cmd .= "send \"$newpwd\\r\"; "; 
    $cmd .= "expect \"passwd: all authentication tokens updated successfully.\"; "; 

    // Commit the command to expect & close 
    fwrite($p, $cmd); pclose ($p); 

    // Read & delete the log 
    $fp = fopen($log,'r'); 
    $output = fread($fp, 2048); 
    fclose($fp); unlink($log); 
    $output = explode("\n",$output); 

    return (trim($output[count($output)-2]) == 'passwd: all authentication tokens updated successfully.') ? true : false; 
} 

function process_post() { 

    if ((!isset($_SERVER['HTTP_REFERER'])) 
     || (strpos($_SERVER['HTTP_REFERER'], $_SERVER['SCRIPT_NAME']) === FALSE)) { 

     echo "GO AWAY!"; 
     exit(); 
     return FALSE; 

    } 

    global $messages; 

    $username   = trim($_POST['username']); 
    $password_current = trim($_POST['password_current']); 
    $password_new  = trim($_POST['password_new']); 
    $password_confirm = trim($_POST['password_confirm']); 

    // Check for blanks 
    if ($username == '' || $password_current == '' || $password_new == '' || $password_confirm == '') { 
     array_push($messages, "ERROR: You cannot leave any field empty."); 
     return FALSE; 
    } 

    // Check username 
    if (!ctype_alnum($username)) { 
     array_push($messages, "ERROR: You've entered an invalid username."); 
     return FALSE; 
    } 

    // Check to see if new password is correctly typed 
    if ($password_new != $password_confirm) {  
     array_push($messages, "ERROR: New Password and Confirmation do not match."); 
     return FALSE; 
    } 

    // Check if current password is valid (not really neccessary) 
    $error = ''; 
    if (!pam_auth($username, $password_current, $error, FALSE)) { 
     if (trim($error) == "Permission denied (in pam_authenticate)") 
      array_push($messages, "ERROR: Your username/password was not accepted.");  
     else 
      array_push($messages, "ERROR: " . $error); 
     return FALSE; 
    } 

    if (change_password ($username, $password_current, $password_new)) 
     array_push($messages, "Password Successfully Changed"); 
    else 
     array_push($messages, "ERROR: Password change failed."); 

} 

if ($_SERVER['REQUEST_METHOD'] == 'POST') process_post(); 


?><html> 
<head> 


<title>Passwords</title> 

<style type="text/css"> 

body { 
    font-family: Verdana, Arial, sans-serif; 
    font-size: 12px; 
} 

label { 
    width: 150px; 
    display: block; 
    float: left; 
} 

input { 
    float: left; 
} 

br { 
    clear: both; 
} 

.message { 
    font-size: 11px; 
    font-weight: bold; 
} 

.error { 
    color:#C00; 
} 


</style> 

</head> 


<body> 

<h2>Change Passwords</h2> 

<form action="<?= $_SERVER['SCRIPT_NAME'] ?>" method="post"> 

<fieldset> 

<? if (count($messages) != 0) { 

    foreach ($messages as $message) { ?> 

<p class="message<?= ((strpos($message, 'ERROR:') === FALSE) ? '' : ' error') ?>"><?= $message ?></p> 

<? } } ?> 

<label>Username: </label> 
<input type="text" name="username" value="halaluya" /><br /> 

<label>Current Password:</label> 
<input type="password" name="password_current" value="[email protected]" /><br /> 

<label>New Password:</label> 
<input type="password" name="password_new" value="123" /><br /> 

<label>Confirm Password:</label> 
<input type="password" name="password_confirm" value="123" /><br /> 

<input type="reset" value="Reset" /> <input type="submit" value="Submit" /> 

</fieldset> 


</form> 


</body> 
</html> 
+0

+1 для настройки php.ini и chmod, эта статья является самой подробной, которую я искал в Интернете. –

1

Изменение паролей PAM непосредственно из PHP, требует большого доступа к вашим системным файлам и службам. Это связано с тем, что по умолчанию PAM использует модуль pam_unix, который хранит учетные данные пользователя в системных файлах, принадлежащих root. Хорошим способом решения этой проблемы является настройка PAM для использования модуля pam_ldap. Таким образом, PAM с аутентифицированными пользователями использует сервер LDAP. Затем с PHP вы можете привязываться к LDAP-серверу с использованием учетных данных пользователя и изменять свой пароль. Авторизация такой модификации может быть решена с помощью механизма авторизации LDAP. (Ваша заявка также должна обеспечивать соблюдение правил авторизации для обеспечения многоуровневой защиты)

Указанная конфигурация не является тривиальной. Сначала вы должны настроить LDAP-сервер, а затем перенести все свои пользовательские данные из системных файлов (passwd, shadow) в каталог LDAP. (для этого есть автоматизированные инструменты). И, наконец, вы должны установить и настроить модуль pam_ldap. Любые неправильные конфигурации в вышеуказанном процессе могут привести к серьезным проблемам безопасности.

Также обратите внимание, что таким образом вы будете подвергать LDAP-сервер веб-сайту через ваше приложение. Любые проблемы безопасности, которые могут повлиять на механизмы аутентификации LDAP или авторизации, также повлияют на безопасность вашей системы.

Ресурсы:

Использование LDAP для хранения POSIX счетов:

http://www.ibm.com/developerworks/linux/library/l-openldap/

Настройка PAM использовать LDAP для аутентификации:

http://wiki.debian.org/LDAP/PAM

+0

Вы упомянули, что есть автоматические инструменты для перехода на LDAP. Есть ли у вас какие-либо ссылки на них? – Azmisov

Смежные вопросы