1<?php 2/** 3 * Copyright 2006-2017 Horde LLC (http://www.horde.org/) 4 * 5 * See the enclosed file COPYING for license information (GPL). If you 6 * did not receive this file, see http://www.horde.org/licenses/gpl. 7 * 8 * @category Horde 9 * @copyright 2006-2017 Horde LLC 10 * @license http://www.horde.org/licenses/gpl GPL 11 * @package Passwd 12 */ 13 14/** 15 * A PECL expect implementation of the Passwd system. 16 * 17 * Copyright 2006-2017 Horde LLC (http://www.horde.org/) 18 * 19 * See the enclosed file COPYING for license information (GPL). If you 20 * did not receive this file, see http://www.horde.org/licenses/gpl. 21 * 22 * @author Duck <duck@obala.net> 23 * @category Horde 24 * @copyright 2006-2017 Horde LLC 25 * @license http://www.horde.org/licenses/gpl GPL 26 * @package Passwd 27 */ 28class Passwd_Driver_Expectpecl extends Passwd_Driver 29{ 30 /** 31 * Expect connection handle. 32 * 33 * @var resource 34 */ 35 protected $_stream; 36 37 /** 38 * Handles expect communication. 39 * 40 * @param string $expect String to expect. 41 * @param string $error Error message. 42 * 43 * @throws Passwd_Exception 44 */ 45 protected function _ctl($expect, $error) 46 { 47 $result = expect_expectl($this->_stream, array( 48 array( 49 0 => $expect, 50 1 => 'ok', 51 2 => EXP_REGEXP 52 ) 53 )); 54 55 switch ($result) { 56 case EXP_EOF: 57 throw new Passwd_Exception(_("End of file.")); 58 59 case EXP_TIMEOUT: 60 throw new Passwd_Exception(_("Time out.")); 61 62 case EXP_FULLBUFFER: 63 throw new Passwd_Exception(_("Full buffer.")); 64 65 case 'ok': 66 return; 67 68 default: 69 throw new Passwd_Exception($error); 70 } 71 } 72 73 /** 74 */ 75 protected function _changePassword($user, $oldpass, $newpass) 76 { 77 if (!Horde_Util::loadExtension('expect')) { 78 throw new Passwd_Exception(_("expect extension cannot be loaded")); 79 } 80 81 // Set up parameters 82 foreach (array('logfile', 'loguser', 'timeout') as $val) { 83 if (isset($this->_params[$val])) { 84 ini_set('expect.' . $val, $this->_params[$val]); 85 } 86 } 87 88 // Open connection 89 $call = sprintf( 90 'ssh %s@%s %s', 91 $user, 92 $this->_params['host'], 93 $this->_params['program'] 94 ); 95 if (!($this->_stream = expect_popen($call))) { 96 throw new Passwd_Exception(_("Unable to open expect stream")); 97 } 98 99 // Log in 100 $this->_ctl( 101 '(P|p)assword.*', 102 _("Could not login to system (no password prompt)") 103 ); 104 105 // Send login password 106 fwrite($this->_stream, $oldpass . "\n"); 107 108 // Expect old password prompt 109 $this->_ctl( 110 '((O|o)ld|login|current).* (P|p)assword.*', 111 _("Could not start passwd program (no old password prompt)") 112 ); 113 114 // Send old password 115 fwrite($this->_stream, $oldpass . "\n"); 116 117 // Expect new password prompt 118 $this->_ctl( 119 '(N|n)ew.* (P|p)assword.*', 120 _("Could not change password (bad old password?)") 121 ); 122 123 // Send new password 124 fwrite($this->_stream, $newpass . "\n"); 125 126 // Expect reenter password prompt 127 $this->_ctl( 128 "((R|r)e-*enter.*(P|p)assword|Retype new( UNIX)? password|(V|v)erification|(V|v)erify|(A|a)gain).*", 129 _("New password not valid (too short, bad password, too similar, ...)") 130 ); 131 132 // Send new password 133 fwrite($this->_stream, $newpass . "\n"); 134 135 // Expect successfully message 136 $this->_ctl( 137 '((P|p)assword.* changed|successfully)', 138 _("Could not change password.") 139 ); 140 } 141 142} 143