@ -15,437 +15,445 @@
* Used to help ensure a server is setup appropriately during installation / setup .
*/
define ( 'POSTFIXADMIN' , 1 ); # by defining it here, common.php will not start a session.
require_once ( dirname ( __FILE__ ) . '/common.php' ); # make sure correct common.php is used.
$CONF [ 'show_header_text' ] = 'NO' ;
$CONF [ 'theme_favicon' ] = 'images/favicon.ico' ;
$CONF [ 'theme_logo' ] = 'images/logo-default.png' ;
$CONF [ 'theme_css' ] = 'css/default.css' ;
require ( dirname ( __FILE__ ) . '/../templates/header.php' );
$configSetupPassword = Config :: read_string ( 'setup_password' );
$errors = [];
$configSetupDone = false ;
$authenticated = false ;
if ( $configSetupPassword != 'changeme' && $configSetupPassword != '' ) {
$configSetupDone = true ;
$pass = safepost ( 'setup_password' , 'invalid' );
if ( $pass != 'invalid' ) {
if ( password_verify ( safepost ( 'setup_password' , 'invalid' ), $configSetupPassword )) {
$authenticated = true ;
} else {
$errors [ 'setup_login_password' ] = " Password verification failed. " ;
}
}
}
?>
< div class = 'setup' >
< h2 > Postfix Admin Setup Checker </ h2 >
< p > Running software :
< ul >
< ? php
//
// Check for availability functions
//
$f_phpversion = function_exists ( " phpversion " );
$f_apache_get_version = function_exists ( " apache_get_version " );
$m_pdo = extension_loaded ( " PDO " );
$m_pdo_mysql = extension_loaded ( " pdo_mysql " );
$m_pdo_pgsql = extension_loaded ( 'pdo_pgsql' );
$m_pdo_sqlite = extension_loaded ( " pdo_sqlite " );
$f_session_start = function_exists ( " session_start " );
$f_preg_match = function_exists ( " preg_match " );
$f_mb_encode_mimeheader = function_exists ( " mb_encode_mimeheader " );
$f_imap_open = function_exists ( " imap_open " );
$file_config = file_exists ( realpath ( " ./../config.inc.php " ));
$file_local_config = file_exists ( realpath ( " ./../config.local.php " ));
// Fall back to looking in /etc/postfixadmin for config.local.php (Debian etc)
if ( ! $file_local_config && is_dir ( '/etc/postfixadmin' )) {
$file_local_config = file_exists ( '/etc/postfixadmin/config.local.php' );
}
< html lang = " " >
< head >
< meta charset = " utf-8 " >
< meta http - equiv = " X-UA-Compatible " content = " IE=edge " >
< meta name = " viewport " content = " width=device-width, initial-scale=1 " >
< meta http - equiv = " Content-Type " content = " text/html; charset=UTF-8 " />
< title > Postfix Admin - Setup </ title >
< link rel = " shortcut icon " href = " images/favicon.ico " />
< link rel = " stylesheet " href = " https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css "
integrity = " sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u " crossorigin = " anonymous " >
<!-- https :// www . srihash . org / -->
< script src = " https://code.jquery.com/jquery-1.12.4.min.js "
integrity = " sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ " crossorigin = " anonymous "
></ script >
< script src = " css/bootstrap-3.4.1-dist/js/moment-with-locales.min.js " ></ script >
< script src = " css/bootstrap-3.4.1-dist/js/bootstrap.min.js " ></ script >
< script src = " css/bootstrap-3.4.1-dist/js/bootstrap-datetimepicker.min.js " ></ script >
</ head >
< body >
< nav class = " navbar navbar-default " >
< div class = " container " >
< div class = " navbar-header " >
< a class = " navbar-brand " href = 'main.php' >
< img id = " login_header_logo " src = " images/logo-default.png "
alt = " Logo " /></ a >
</ div >
</ div >
</ nav >
$error = 0 ;
< ? php
$todo = '<span class="font-weight-bold text-primary">TODO</span>' ;
$authenticatedLabel = $todo ;
$errormsg = array ();
$configSetupLabel = $todo ;
$tick = ' ✅ ' ;
//
// Check for PHP version
//
$phpversion = 'unknown-version' ;
if ( $f_phpversion == 1 ) {
if ( version_compare ( phpversion (), '5' , '<' )) {
print " <li><b>Error: Depends on: PHP v5+</b><br /></li> \n " ;
$error += 1 ;
} elseif ( version_compare ( phpversion (), '7.0' ) < 0 ) {
$phpversion = 5 ;
print " <li><b>Recommended PHP version: >= 7.0, you have " . phpversion () . " ; you should upgrade.</b></li> \n " ;
} else {
print " <li>PHP version " . phpversion () . " - Good</li> \n " ;
}
} else {
print " <li><b style='color: red'>DANGER</b> Unable to check for PHP version. (missing function: phpversion())</b></li> \n " ;
$error ++ ;
}
if ( $configSetupDone ) {
$configSetupLabel = $tick ;
//
// Check for Apache version
//
if ( $f_apache_get_version == 1 ) {
print " <li> " . apache_get_version () . " </li> \n " ;
} else {
# not running on Apache.
# However postfixadmin _is_ running, so obviously we are on a supported webserver ;-))
# No need to confuse the user with a warning.
}
if ( $authenticated ) {
$authenticatedLabel = $tick ;
}
}
?>
print " </ul> " ;
print " <p>Checking environment: \n " ;
print " <ul> \n " ;
< div class = " container " >
//
// Check for config.local.php
//
if ( $file_local_config == 1 ) {
print " <li>Depends on: presence config.local.php - Found</li> \n " ;
} else {
print " <li><b>Warning: config.local.php - NOT FOUND</b><br /></li> \n " ;
print " It's Recommended to store your own settings in config.local.php instead of editing config.inc.php<br /> " ;
print " Create the file, and edit as appropriate (e.g. select database type etc)<br /> " ;
}
< div class = " row " >
< ? php
// Check if there is support for at least 1 database
if (( $m_pdo == 0 ) and ( $m_pdo_mysql == 0 ) and ( $m_pdo_sqlite == 0 ) and ( $m_pdo_pgsql == 0 ) ) {
print " <li><b>Error: There is no database (PDO) support in your PHP setup</b><br /> \n " ;
print " <span style='color: red'>
You MUST install a suitable PHP PDO extension ( e . g . pdo_pgsql , pdo_mysql or pdo_sqlite ) .
</ span > \n </ li > " ;
$error += 1 ;
}
if ( ! isset ( $_SERVER [ 'HTTPS' ])) {
echo " <h2 class='h2 text-danger'>Warning: connection not secure, switch to https if possible</h2> " ;
} ?>
if ( $m_pdo_mysql == 1 ) {
print " <li>Database - PDO MySQL - Found</li> " ;
} else {
print " <li>Database - MySQL (pdo_mysql) extension not found</li> " ;
}
< div class = " col-12 " >
< h1 > Configure and Setup Postfixadmin </ h1 >
//
// PostgreSQL functions
//
if ( $m_pdo_pgsql == 1 ) {
print " <li>Database : PDO PostgreSQL - Found \n " ;
if ( Config :: read_string ( 'database_type' ) != 'pgsql' ) {
print " <br>(change the database_type to 'pgsql' in config.local.php if you want to use PostgreSQL) \n " ;
}
print " </li> " ;
< ul >
< li >< ? = $configSetupLabel ?> You need to have a setup_password configured in a
< code > config . local . php </ code > file .
</ li >
< li >< ? = $authenticatedLabel ?> Login using your setup password.</li>
< li > Then you can run some self tests to check compatability with
Postfixadmin
</ li >
< li > Create / update your database of choice </ li >
< li > and Add a new super user account </ li >
</ ul >
< p >
If we do have a setup_password configured ; show the form to generate a new one , as well as a form to
allow
someone
to authenticate as setup - admin
</ p >
< p >
If someone has submitted the setup form to login , then set $_SESSION [ 'setupadmin' ] = true and display
setup / env
check stuff as well as allowing them to add a new super - admin account .
</ p >
</ div >
</ div >
< ? php if ( $configSetupDone && ! $authenticated ) { ?>
< div class = " row " >
< h2 class = " h2 " > Login with setup_password </ h2 >
< p > If you ' ve forgotten your super - admin password , you can generate a new one using the < em > Generate </ em >
form
and update your < code > config . local . php </ code ></ p >
< form name = " authenticate " class = " form-horizontal " method = " post " >
< div class = " form-group " >
< label for = " setup_password " class = " col-sm-4 control-label " > Setup password </ label >
< div class = " col-sm-4 " >
< input class = " form-control " type = " password " name = " setup_password " minlength = 5
id = " setup_password "
value = " " />
< ? = _error_field ( $errors , 'setup_login_password' ); ?>
</ div >
</ div >
< div class = " form-group " >
< div class = " col-sm-offset-4 col-sm-4 " >
< button class = " btn btn-primary " type = " submit " name = " submit " value = " setuppw " > Login with
setup_password .
</ button >
</ div >
</ div >
</ form >
</ div >
< ? php } ?>
< div class = " row " >
< ? php
if ( ! $configSetupDone ) {
echo <<< EOF
< p >< strong > For a new installation , you must generate a 'setup_password' to go into your config . local . php file .</ strong ></ p >
< p > You can use the form below , or run something like the following in a shell - < code > php - r 'echo password_hash("password", PASSWORD_DEFAULT);' </ code >< p >
EOF ;
}
?>
< ? php
if ( ! $authenticated || ! $configSetupDone ) { ?>
< h2 > Generate setup_password hash </ h2 >
< ? php
$form_error = '' ;
$result = '' ;
if ( safepost ( 'form' ) === " setuppw " ) {
$errors = [];
# "setup password" form submitted
if ( safepost ( 'setup_password' , 'abc' ) != safepost ( 'setup_password2' )) {
$errors [ 'setup_password' ] = " The two passwords differ! " ;
$form_error = 'has-error' ;
} else {
print " <li>Database - PostgreSQL (pdo_pgsql) extension not found</li> " ;
}
$msgs = validate_password ( safepost ( 'setup_password' ));
if ( empty ( $msgs )) {
// form has been submitted; both fields filled in, so generate a new setup password.
$hash = password_hash ( safepost ( 'setup_password' ), PASSWORD_DEFAULT );
if ( $m_pdo_sqlite == 1 ) {
print " <li>Database : PDO SQLite - Found \n " ;
if ( Config :: read_string ( 'database_type' ) != 'sqlite' ) {
print " <br>(change the database_type to 'sqlite' in config.local.php if you want to use SQLite) \n " ;
$result = '<p>If you want to use the password you entered as setup password, edit config.inc.php or config.local.php and set</p>' ;
$result .= " <pre> \$ CONF['setup_password'] = ' $hash ';</pre> " ;
} else {
$form_error = 'has-error' ;
$errors [ 'setup_password' ] = implode ( ', ' , $msgs );
}
print " </li> " ;
} else {
print " <li>Database - SQLite (pdo_sqlite) extension not found</li> " ;
}
}
//
// Database connection
//
$link = null ;
$error_text = null ;
?>
try {
$link = db_connect ();
} catch ( Exception $e ) {
$error_text = $e -> getMessage ();
}
< form name = " setuppw " method = " post " class = " form-horizontal " action = " setup.php " >
< input type = " hidden " name = " form " value = " setuppw " />
if ( ! empty ( $link ) && $error_text == " " ) {
print " <li>Testing database connection (using { $CONF [ 'database_type' ] } ) - Success</li> " ;
} else {
print " <li><b style='color: red'>Error: Can't connect to database</b><br /> \n " ;
print " Please check the \$ CONF['database_*'] parameters in config.local.php.<br /> \n " ;
print " $error_text </li> \n " ;
$error ++ ;
}
< div class = " form-group <?= $form_error ?> " >
//
// Session functions
//
if ( $f_session_start == 1 ) {
print " <li>Depends on: session - OK</li> \n " ;
} else {
print " <li><b>Error: Depends on: session - NOT FOUND</b><br /> \n " ;
print " To install session support on FreeBSD:<br /> \n " ;
print " <pre>% cd /usr/ports/www/php $phpversion -session/ \n " ;
print " % make clean install \n " ;
print " - or with portupgrade - \n " ;
print " % portinstall php $phpversion -session</pre></li> \n " ;
$error += 1 ;
< label for = " setup_password " class = " col-sm-4 control-label " > Setup password </ label >
< div class = " col-sm-4 " >
< input class = " form-control " type = " password " name = " setup_password " minlength = 5
id = " setup_password "
autocomplete = " new-password "
value = " " />
< ? = _error_field ( $errors , 'setup_password' ); ?>
</ div >
</ div >
< div class = " form-group <?= $form_error ?> " >
< label for = " setup_password2 " class = " col-sm-4 control-label " > Setup password ( again ) </ label >
< div class = " col-sm-4 " >
< input class = " form-control " type = " password " name = " setup_password2 "
minlength = 5 id = " setup_password2 "
autocomplete = " new-password "
value = " " />
< ? = _error_field ( $errors , 'setup_password2' ); ?>
</ div >
</ div >
< div class = " form-group " >
< div class = " col-sm-offset-4 col-sm-4 " >
< button class = " btn btn-primary " type = " submit " name = " submit " value = " setuppw " > Generate setup_password
hash
</ button >
</ div >
</ div >
</ form >
< ? = $result ?>
</ div >
< ? php } // end if(!$authenticated) ?>
< div class = " row " >
< h2 > Hosting Environment Check </ h2 >
< ? php
$check = do_software_environment_check ();
if ( $authenticated ) {
if ( ! empty ( $check [ 'error' ])) {
echo " <p><p>Errors were found with your environment. These will be displayed once you've configured a setup_password and confirmed it.</p> " ;
}
//
// PCRE functions
//
if ( $f_preg_match == 1 ) {
print " <li>Depends on: pcre - Found</li> \n " ;
} else {
print " <li><b>Error: Depends on: pcre - NOT FOUND</b><br /> \n " ;
print " To install pcre support on FreeBSD:<br /> \n " ;
print " <pre>% cd /usr/ports/devel/php $phpversion -pcre/ \n " ;
print " % make clean install \n " ;
print " - or with portupgrade - \n " ;
print " % portinstall php $phpversion -pcre</pre></li> \n " ;
$error += 1 ;
if ( ! empty ( $check [ 'info' ])) {
echo " <h3>Information</h3><ul> " ;
foreach ( $check [ 'info' ] as $msg ) {
echo " <li> { $tick } { $msg } </li> " ;
}
echo " </ul> " ;
}
//
// Multibyte functions
//
if ( $f_mb_encode_mimeheader == 1 ) {
print " <li>Depends on: multibyte string - Found</li> \n " ;
} else {
print " <li><b>Error: Depends on: multibyte string - mbstring extension missing.</b><br /> \n " ;
print " To install multibyte string support, perhaps install php $phpversion -mbstring</li> \n " ;
$error += 1 ;
if ( ! empty ( $check [ 'warn' ])) {
echo " <h3>Warnings</h3><ul> " ;
foreach ( $check [ 'warn' ] as $msg ) {
echo " <li class='text-warning'>⚠ { $msg } </li> " ;
}
echo " </ul> " ;
}
if ( ! empty ( $check [ 'error' ])) {
echo " <h3>Errors (MUST be fixed)</h3><ul> " ;
foreach ( $check [ 'error' ] as $msg ) {
echo " <li class='text-danger'>⛔ { $msg } </li> " ;
}
echo " </ul> " ;
}
} else {
if ( ! empty ( $check [ 'error' ])) {
echo '<h3 class="text-danger">Hosting Environment errors found. Login to see details.</h3>' ;
}
if ( ! empty ( $check [ 'warn' ])) {
echo '<h3 class="text-warning">Hosting Environment warnings found. Login to see details.</h3>' ;
}
}
?>
//
// Imap functions
//
if ( $f_imap_open == 1 ) {
print " <li>IMAP functions - Found</li> \n " ;
} else {
print " <li><b>Warning: Optional dependency 'imap' extension missing</b><br /> \n " ;
print " To install IMAP support, perhaps install php $phpversion -imap<br /> \n " ;
print " Without IMAP support, you won't be able to create subfolders when creating mailboxes.</li> \n " ;
}
</ div >
< div class = " row " >
//
// If PHP <7.0, require random_compat works. Currently we bundle it via the Phar extension.
//
< h2 > Database Update </ h2 >
if ( version_compare ( phpversion (), " 7.0 " , '<' )
&& ! extension_loaded ( 'Phar' )
&& $CONF [ 'configured' ]
&& $CONF [ 'encrypt' ] == 'php_crypt' ) {
print " <li>PHP before 7.0 requires 'Phar' extension support for <strong>secure</strong> random_int() function fallback " ;
print " <br/>Either enable the 'Phar' extension, or install the random_compat library files from <a href='https://github.com/paragonie/random_compat'>https://github.com/paragonie/random_compat</a> and include/require them from functions.inc.php " ;
print " <br/>PostfixAdmin has bundled lib/random_compat.phar but it's not usable on your installation due to the missing Phar extension.</li> " ;
$error += 1 ;
}
< ? php
if ( $authenticated ) {
print " <p>Everything seems fine... attempting to create/update database structure</p> \n " ;
require_once ( dirname ( __FILE__ ) . '/upgrade.php' );
} else {
echo " <h3 class='text-warning'>Please login to see perform database update.</h3> " ;
}
?>
</ div >
print " </ul> " ;
< ? php
if ( $authenticated ) {
?>
< div class = " row " >
< h2 > Add Superadmin Account </ h2 >
if ( $error != 0 ) {
print " <p><b>Please fix the errors listed above.</b></p> " ;
} else {
print " <p>Everything seems fine... attempting to create/update database structure</p> \n " ;
require_once ( dirname ( __FILE__ ) . '/upgrade.php' );
$tUsername = '' ;
$setupMessage = '' ;
$lostpw_error = 0 ;
< form name = " create_admin " class = " form-horizontal " method = " post " >
$setuppw = " " ;
if ( isset ( $CONF [ 'setup_password' ])) {
$setuppw = $CONF [ 'setup_password' ];
}
if ( safepost ( " form " ) === " setuppw " ) {
# "setup password" form submitted
if ( safepost ( 'setup_password' ) != safepost ( 'setup_password2' )) {
$setupMessage = " The two passwords differ! " ;
$lostpw_error = 1 ;
} else {
list ( $lostpw_error , $lostpw_result ) = check_setup_password ( safepost ( 'setup_password' ), 1 );
$setupMessage = $lostpw_result ;
$setuppw = " changed " ;
}
} elseif ( safepost ( " form " ) == " createadmin " ) {
# "create admin" form submitted
list ( $pw_check_error , $pw_check_result ) = check_setup_password ( safepost ( 'setup_password' ));
if ( $pw_check_result != 'pass_OK' ) {
$error += 1 ;
$setupMessage = $pw_check_result ;
}
if ( $error == 0 && $pw_check_result == 'pass_OK' ) {
// XXX need to ensure domains table includes an 'ALL' entry.
$table_domain = table_by_key ( 'domain' );
$rows = db_query_all ( " SELECT * FROM $table_domain WHERE domain = 'ALL' " );
if ( empty ( $rows )) {
db_insert ( 'domain' , array ( 'domain' => 'ALL' , 'description' => '' , 'transport' => '' )); // all other fields should default through the schema.
}
$values = array (
'username' => safepost ( 'username' ),
'password' => safepost ( 'password' ),
'password2' => safepost ( 'password2' ),
'superadmin' => 1 ,
'domains' => array (),
'active' => 1 ,
);
list ( $error , $setupMessage , $errormsg ) = create_admin ( $values );
if ( $error != 0 ) {
$tUsername = htmlentities ( $values [ 'username' ]);
} else {
$setupMessage .= " <p>You are done with your basic setup. " ;
$setupMessage .= " <p><b>You can now <a href='login.php'>login to PostfixAdmin</a> using the account you just created.</b> " ;
}
}
}
< div class = " form-group " >
< label for = " setup_password " class = " col-sm-4 control-label " > Setup password </ label >
< div class = " col-sm-4 " >
< input class = " form-control " type = " text " required = " required " name = " setup_password " minlength = 5
value = " " />
</ div >
</ div >
if ( ! isset ( $_SERVER [ 'HTTPS' ])) {
echo " <h2>Warning: connection not secure, switch to https if possible</h2> " ;
} ?>
< div class = " standout " >< ? php print $setupMessage ; ?> </div>
< div class = " form-group " >
< label for = " username " class = " col-sm-4 control-label " >< ? = $PALANG [ 'admin' ] ?> </label>
< div class = " col-sm-4 " >
< input class = " form-control " type = " text " required = " required " name = " username " minlength = 5
id = " username "
value = " " />
< ? php
$change = " Change " ;
< ? = _error_field ( $errors , 'username' ); ?>
if ( Config :: read_string ( 'setup_password' ) == '' || Config :: read_string ( 'setup_password' ) == 'changeme' ) {
echo <<< EOF
< p >< strong > For a new installation , you need to generate a 'setup_password' to go into your config . local . php file .</ strong ></ p >
< p > You can use the form below , or run something like < pre > php - r 'echo "somesalt:" . sha1("somesalt:" . "password");' </ pre > in a shell , after changing the salt .< p >
EOF ;
$change = " Generate " ;
} ?>
< h2 >< ? = $change ?> $CONF['setup_password']</h2>
< div id = " edit_form " >
< form name = " setuppw " method = " post " action = " setup.php " >
< input type = " hidden " name = " form " value = " setuppw " />
< table >
< tr >
< td >< label for = " setup_password " > Setup password </ label ></ td >
< td >< input class = " flat " type = " password " name = " setup_password " minlength = 5 id = " setup_password " value = " " /></ td >
< td ></ td >
</ tr >
< tr >
< td >< label for = " setup_password2 " > Setup password ( again ) </ label ></ td >
< td >< input class = " flat " type = " password " name = " setup_password2 " minlength = 5 id = " setup_password2 " value = " " /></ td >
< td ></ td >
</ tr >
< tr >
< td colspan = " 3 " class = " hlp_center " >< input class = " button " type = " submit " name = " submit " value = " Generate password hash " /></ td >
</ tr >
</ table >
</ form >
</ div >
</ div >
< ? php
if ( $change != 'Generate' ) { ?>
< h2 > Add a SuperAdmin Account </ h2 >
< div id = " edit_form " >
< form name = " create_admin " method = " post " >
< input type = " hidden " name = " form " value = " createadmin " />
< table >
< tr >
< td >< label for = " setup_password " > Setup password </ label ></ td >
< td >< input id = setup_password class = " flat " type = " password " name = " setup_password " value = " " /></ td >
< td >< ? = _error_field ( $errormsg , 'setup_password' ); ?> <?php print $PALANG['setup_password'] ?></td>
</ tr >
< tr >
< td >< label for = " username " >< ? php print $PALANG [ 'admin' ] . " : " ; ?> </label></td>
< td >< input id = " username " class = " flat " type = " text " name = " username " value = " <?php print $tUsername ; ?> " /></ td >
< td >< ? = _error_field ( $errormsg , 'username' ); ?> <?php print $PALANG['email_address'] ?></td>
</ tr >
< tr >
< td >< label for = " password " >< ? php print $PALANG [ 'password' ] . " : " ; ?> </label></td>
< td >< input id = " password " class = " flat " type = " password " name = " password " autocomplete = " new-password " /></ td >
< td >< ? = _error_field ( $errormsg , 'password' ); ?> </td>
</ tr >
< tr >
< td >< label for = " password2 " >< ? php print $PALANG [ 'password_again' ] . " : " ; ?> </label></td>
< td >< input id = " password2 " class = " flat " type = " password " name = " password2 " autocomplete = " new-password " /></ td >
< td >< ? = _error_field ( $errormsg , 'password2' ); ?> </td>
</ tr >
< tr >
< td colspan = " 3 " class = " hlp_center " >< input class = " button " type = " submit " name = " submit " value = " <?php print $PALANG['pAdminCreate_admin_button'] ; ?> " /></ td >
</ tr >
</ table >
</ form >
< div class = " form-group " >
< label for = " password " class = " col-sm-4 control-label " >< ? = $PALANG [ 'password' ] ?> </label>
< div class = " col-sm-4 " >
< input class = " form-control " type = " password " required = required
name = " password " minlength = 5
id = " password " autocomplete = " new-password "
value = " " />
< ? = _error_field ( $errors , 'password' ); ?>
</ div >
</ div >
< ? php
}
} ?>
< p > Since version 2.3 there is no requirement to delete setup . php </ p >
< p > Check the config . inc . php file for any other settings that you may need to change .</ p >
< div class = " form-group " >
< label for = " password2 " class = " col-sm-4 control-label " >< ? = $PALANG [ 'password_again' ] ?> </label>
< div class = " col-sm-4 " >
< input class = " form-control " type = " password " required = required
name = " password2 " minlength = 5
id = " password2 " autocomplete = " new-password "
value = " " />
</ div >
</ body >
</ html >
< ? php
< ? = _error_field ( $errors , 'password2' ); ?>
function _error_field ( $errors , $key ) {
if ( ! isset ( $errors [ $key ])) {
return '' ;
}
return " <span style='color: red'> { $errors [ $key ] } </span> " ;
}
</ div >
</ div >
function generate_setup_password_salt () {
$salt = time () . '*' . $_SERVER [ 'REMOTE_ADDR' ] . '*' . mt_rand ( 0 , 60000 );
$salt = md5 ( $salt );
return $salt ;
}
function encrypt_setup_password ( $password , $salt ) {
return $salt . ':' . sha1 ( $salt . ':' . $password );
}
< div class = " form-group " >
< div class = " col-sm-offset-4 col-sm-4 " >
< button class = " btn btn-primary " type = " submit " name = " submit "
value = " setuppw " >< ? = $PALANG [ 'pAdminCreate_admin_button' ] ?>
</ button >
</ div >
</ div >
</ form >
</ div >
/*
returns : array (
'error' => 0 ( or 1 ),
' message => text
)
*/
function check_setup_password ( $password , $lostpw_mode = 0 ) {
global $CONF ;
$error = 1 ; # be pessimistic
< ? php }
$setuppw = " " ;
if ( isset ( $CONF [ 'setup_password' ])) {
$setuppw = $CONF [ 'setup_password' ];
}
if ( safepost ( " form " ) === " createadmin " && $authenticated ) {
# "create admin" form submitted, make sure the correct setup password was specified.
list ( $confsalt , $confpass , $trash ) = explode ( ':' , $setuppw . '::' );
$pass = encrypt_setup_password ( $password , $confsalt );
// XXX need to ensure domains table includes an 'ALL' entry.
$table_domain = table_by_key ( 'domain' );
$rows = db_query_all ( " SELECT * FROM $table_domain WHERE domain = 'ALL' " );
if ( empty ( $rows )) {
// all other fields should default through the schema.
db_insert ( 'domain' , array ( 'domain' => 'ALL' , 'description' => '' , 'transport' => '' ));
}
$validpass = validate_password ( $password );
$values = array (
'username' => safepost ( 'username' ),
'password' => safepost ( 'password' ),
'password2' => safepost ( 'password2' ),
'superadmin' => 1 ,
'domains' => array (),
'active' => 1 ,
);
if ( $password == " " ) { # no password specified?
$result = " Setup password must be specified<br />If you didn't set up a setup password yet, enter the password you want to use. " ;
} elseif ( count ( $validpass ) > 0 ) {
$result = $validpass [ 0 ]; # TODO: honor all error messages, not only the first one
} elseif ( $pass == $setuppw && $lostpw_mode == 0 ) { # correct passsword (and not asking for a new password)
$result = " pass_OK " ;
$error = 0 ;
} else {
$pass = encrypt_setup_password ( $password , generate_setup_password_salt ());
$result = " " ;
if ( $lostpw_mode == 1 ) {
$error = 0 ; # non-matching password is expected when the user asks for a new password
list ( $error , $setupMessage , $errormsg ) = create_admin ( $values );
if ( $error == 1 ) {
$tUsername = htmlentities ( $values [ 'username' ]);
} else {
$result = '<p><b>Setup password not specified correctly</b></p>' ;
// all good!.
$setupMessage .= " <p>You are done with your basic setup. " ;
$setupMessage .= " <p><b>You can now <a href='login.php'>login to PostfixAdmin</a> using the account you just created.</b> " ;
}
$result .= '<p>If you want to use the password you entered as setup password, edit config.inc.php or config.local.php and set</p>' ;
$result .= " <pre> \$ CONF['setup_password'] = ' $pass ';</pre> " ;
}
return array ( $error , $result );
?>
</ div >
</ div >
< footer class = " footer mt-5 bg-dark " >
< div class = " container text-center " >< a target = " _blank " rel = " noopener "
href = " https://github.com/postfixadmin/postfixadmin/ " > Postfix Admin </ a >
</ div >
</ footer >
</ body >
</ html >
< ? php
function _error_field ( $errors , $key )
{
if ( ! isset ( $errors [ $key ])) {
return '' ;
}
return " <span style='color: #ff0000'> { $errors [ $key ] } </span> " ;
}
function create_admin ( $values ) {
DEFINE ( 'POSTFIXADMIN_SETUP' , 1 ); # avoids instant redirect to login.php after creating the admin
function create_admin ( $values )
{
define ( 'POSTFIXADMIN_SETUP' , 1 ); # avoids instant redirect to login.php after creating the admin
$handler = new AdminHandler ( 1 , 'setup.php' );
$formconf = $handler -> webformConfig ();
@ -469,6 +477,173 @@ function create_admin($values) {
);
}
/**
* @ return array [ 'info' => string [], 'warn' => string [], 'error' => string [] ]
*/
function do_software_environment_check ()
{
$CONF = Config :: getInstance () -> getAll ();
$warn = [];
$error = [];
$info = [];
//
// Check for availability functions
//
$f_phpversion = function_exists ( " phpversion " );
$f_apache_get_version = function_exists ( " apache_get_version " );
$m_pdo = extension_loaded ( " PDO " );
$m_pdo_mysql = extension_loaded ( " pdo_mysql " );
$m_pdo_pgsql = extension_loaded ( 'pdo_pgsql' );
$m_pdo_sqlite = extension_loaded ( " pdo_sqlite " );
$f_session_start = function_exists ( " session_start " );
$f_preg_match = function_exists ( " preg_match " );
$f_mb_encode_mimeheader = function_exists ( " mb_encode_mimeheader " );
$f_imap_open = function_exists ( " imap_open " );
$file_local_config = file_exists ( realpath ( " ./../config.local.php " ));
// Fall back to looking in /etc/postfixadmin for config.local.php (Debian etc)
if ( ! $file_local_config && is_dir ( '/etc/postfixadmin' )) {
$file_local_config = file_exists ( '/etc/postfixadmin/config.local.php' );
}
//
// Check for PHP version
//
$phpversion = 'unknown-version' ;
if ( $f_phpversion == 1 ) {
if ( version_compare ( phpversion (), '5' , '<' )) {
$error [] = " Error: Depends on: PHP v5+ " ;
} elseif ( version_compare ( phpversion (), '7.0' ) < 0 ) {
$phpversion = 5 ;
$info [] = " Recommended PHP version: >= 7.0, you have " . phpversion () . " ; you should upgrade. " ;
} else {
$info [] = " PHP version " . phpversion ();
}
} else {
$error [] = " Unable to check for PHP version. (missing function: phpversion()) " ;
}
//
// Check for Apache version
//
if ( $f_apache_get_version == 1 ) {
$info [] = apache_get_version ();
}
//
// Check for config.local.php
//
if ( $file_local_config == 1 ) {
$info [] = " Depends on: presence config.local.php - Found " ;
} else {
$warn [] = " <b>Warning: config.local.php - NOT FOUND - It's Recommended to store your own settings in config.local.php instead of editing config.inc.php " ;
}
// Check if there is support for at least 1 database
if (( $m_pdo == 0 ) and ( $m_pdo_mysql == 0 ) and ( $m_pdo_sqlite == 0 ) and ( $m_pdo_pgsql == 0 )) {
$error [] = " There is no database (PDO) support in your PHP setup, you MUST install a suitable PHP PDO extension (e.g. pdo_pgsql, pdo_mysql or pdo_sqlite). " ;
}
if ( $m_pdo_mysql == 1 ) {
$info [] = " Database - PDO MySQL - Found " ;
} else {
$info [] = " Database - MySQL (pdo_mysql) extension not found " ;
}
//
// PostgreSQL functions
//
if ( $m_pdo_pgsql == 1 ) {
$info [] = " Database support : PDO PostgreSQL - Found " ;
if ( Config :: read_string ( 'database_type' ) != 'pgsql' ) {
$warn [] = " Change the database_type to 'pgsql' in config.local.php if you want to use PostgreSQL " ;
}
} else {
$warn [] = " Database - PostgreSQL (pdo_pgsql) extension not found " ;
}
if ( $m_pdo_sqlite == 1 ) {
$info [] = " Database support : PDO SQLite - Found " ;
if ( Config :: read_string ( 'database_type' ) != 'sqlite' ) {
$warn [] = " Change the database_type to 'sqlite' in config.local.php if you want to use SQLite " ;
}
} else {
$warn [] = " Database support - SQLite (pdo_sqlite) extension not found " ;
}
$link = null ;
$error_text = null ;
try {
$link = db_connect ();
} catch ( Exception $e ) {
$error_text = $e -> getMessage ();
}
if ( ! empty ( $link ) && $error_text == " " ) {
$info [] = " Testing database connection (using { $CONF [ 'database_type' ] } ) - Success " ;
} else {
$error [] = " Error: Can't connect to database - please check the \$ CONF['database_*'] parameters in config.local.php : $error_text " ;
}
//
// Session functions
//
if ( $f_session_start == 1 ) {
$info [] = " Depends on: session - OK " ;
} else {
$error [] = " Error: Depends on: session - NOT FOUND. (FreeBSD: portinstall php $phpversion -session ?). " ;
}
//
// PCRE functions
//
if ( $f_preg_match == 1 ) {
$info [] = " Depends on: pcre - Found " ;
} else {
$error [] = " Error: Depends on: pcre - NOT FOUND. (FreeBSD: portinstall php $phpversion -pcre) " ;
}
//
// Multibyte functions
//
if ( $f_mb_encode_mimeheader == 1 ) {
$info [] = " Depends on: multibyte string - Found " ;
} else {
$error [] = " Error: Depends on: multibyte string - mbstring extension missing. (FreeBSD: portinstall php $phpversion -mbstring?) " ;
}
//
// Imap functions
//
if ( $f_imap_open == 1 ) {
$info [] = " IMAP functions - Found " ;
} else {
$warn [] = " Warning: Optional dependency 'imap' extension missing, without this you may not be able to automcate creation of subfolders for new mailboxes) " ;
}
//
// If PHP <7.0, require random_compat works. Currently we bundle it via the Phar extension.
//
if ( version_compare ( phpversion (), " 7.0 " , '<' )
&& ! extension_loaded ( 'Phar' )
&& $CONF [ 'configured' ]
&& $CONF [ 'encrypt' ] == 'php_crypt' ) {
$error [] = " PHP before 7.0 requires 'Phar' extension support for <strong>secure</strong> random_int() function fallback. Either enable the 'Phar' extension, or install the random_compat library files from <a href='https://github.com/paragonie/random_compat'>https://github.com/paragonie/random_compat</a> and include/require them from functions.inc.php " ;
$error [] = " PostfixAdmin has bundled lib/random_compat.phar but it's not usable on your installation due to the missing Phar extension. " ;
}
return [ 'error' => $error , 'warn' => $warn , 'info' => $info ];
}
/* vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */
?>