| 1 |
<?php
|
| 2 |
/* $Id$ */
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file
|
| 6 |
* Allows ISP users, including virtual domain users to log in using their POP3 or IMAP accounts.
|
| 7 |
*/
|
| 8 |
|
| 9 |
/**
|
| 10 |
* Implementation of hook_help().
|
| 11 |
*/
|
| 12 |
function isp_login_help($section) {
|
| 13 |
switch ($section) {
|
| 14 |
case 'admin/help#isp_login':
|
| 15 |
return t(
|
| 16 |
"<p>The ISP Login module lets users log in using any IMAP or POP3 email accounts. It is mainly intended for ISPs, which have lots os virtual domains per server, and maybe different login methods on different servers.</p>
|
| 17 |
<p>The user must login using his complete e-mail address, in the form <strong><em>user@mail_domain</em></strong>, and the corresponding password. Then the module tries to open a POP3 or IMAP connection. If it succeeds the user is allowed in, and a new drupal account is created for him if necessary.</p>
|
| 18 |
The module:
|
| 19 |
<ul>
|
| 20 |
<li>Queries the DNS system for the MX host designated for <em>mail_domain</em>. The returned value is the <em>mail_host</em></li>
|
| 21 |
<li>If no MX record is returned, then it assumes that <em>mail_domain</em> is a host (not a domain) and must be the <em>mail_host</em> itself</li>
|
| 22 |
<li>If <em>mail_host</em> is still a DNS name, it is converted in an IP address using other DNS query.</li>
|
| 23 |
<li>If <em>mail_host</em> is <em>not listed</em> on the !LSP the login is <em>denied</em></li>
|
| 24 |
<li>If it is, the module tries to connect to <em>mail_host</em> using the method described there. The login is allowed if the connection succeeds, and denied otherwise.</li>
|
| 25 |
</ul>
|
| 26 |
<p>See the !LSP for more information about the available login methods.</p>",
|
| 27 |
array('!LSP' => l(t('ISP Login settings page'),'admin/user/isp_login'))
|
| 28 |
);
|
| 29 |
}
|
| 30 |
}
|
| 31 |
|
| 32 |
|
| 33 |
/**
|
| 34 |
* Implementation of hook_menu().
|
| 35 |
*/
|
| 36 |
function isp_login_menu($may_cache) {
|
| 37 |
$items[] = array(
|
| 38 |
'path' => 'admin/user/isp_login',
|
| 39 |
'title' => t('ISP Login'),
|
| 40 |
'description' => t('List the IMAP or POP3 servers that are allowed to authenticate users.'),
|
| 41 |
'callback' => 'drupal_get_form',
|
| 42 |
'callback arguments' => 'isp_login_settings',
|
| 43 |
);
|
| 44 |
return $items;
|
| 45 |
}
|
| 46 |
|
| 47 |
/**
|
| 48 |
* Implementation of hook_auth().
|
| 49 |
*/
|
| 50 |
function isp_login_auth($username,$password,$mail_domain) {
|
| 51 |
if (variable_get('isp_login_enabled',0) == 0) return FALSE;
|
| 52 |
if (empty($username) || empty($password) || empty($mail_domain)) return FALSE;
|
| 53 |
|
| 54 |
if (!function_exists('imap_open')) {
|
| 55 |
// IMAP extension not loaded
|
| 56 |
watchdog('isp_login',t(
|
| 57 |
'IMAP extension not loaded. isp_login module couldn\'t be used to authenticate users.'
|
| 58 |
),WATCHDOG_WARNING);
|
| 59 |
return FALSE;
|
| 60 |
}
|
| 61 |
|
| 62 |
// get the mail server IP
|
| 63 |
$mail_domain = trim($mail_domain);
|
| 64 |
if (getmxrr($mail_domain,$mxhosts)) {
|
| 65 |
// $mail_domain returns a MX record. Use it.
|
| 66 |
$mail_host = gethostbyname($mxhosts[0]);
|
| 67 |
} else {
|
| 68 |
// No MX. So, $mail_domain must be the mail host itself.
|
| 69 |
$mail_host = gethostbyname($mail_domain);
|
| 70 |
}
|
| 71 |
|
| 72 |
// get the allowed servers list
|
| 73 |
$lines = preg_split("/[\n\r]+/",variable_get('isp_login_servers',''));
|
| 74 |
$cfg = array();
|
| 75 |
foreach ($lines as $line) {
|
| 76 |
$line = preg_replace("/ +/",'',$line);
|
| 77 |
if (!$line) continue;
|
| 78 |
list($ip,$mailbox,$mode) = preg_split("/,/",$line);
|
| 79 |
if (!$ip || !$mailbox || !$mode) continue;
|
| 80 |
$cfg[$ip]['mbox'] = $mailbox;
|
| 81 |
$cfg[$ip]['mode'] = $mode;
|
| 82 |
}
|
| 83 |
if (empty($cfg)) return FALSE;
|
| 84 |
|
| 85 |
// check the login mail host
|
| 86 |
$mailbox = $cfg[$mail_host]['mbox'];
|
| 87 |
if (!$mailbox) return FALSE;
|
| 88 |
$mode = $cfg[$mail_host]['mode'];
|
| 89 |
if (!$mode) return FALSE;
|
| 90 |
switch ($mode) {
|
| 91 |
case 'did':
|
| 92 |
if (!function_exists('dns_get_record')) return FALSE;
|
| 93 |
$rec = dns_get_record('domain-id.'.$mail_domain,DNS_TXT);
|
| 94 |
$login = preg_replace('/%user%/',$username,$rec[0]['txt']);
|
| 95 |
break;
|
| 96 |
case 'plain':
|
| 97 |
$login = $username;
|
| 98 |
break;
|
| 99 |
default:
|
| 100 |
$login = $username.$cfg[$mail_host]['mode'].$mail_domain;
|
| 101 |
}
|
| 102 |
$org_login = $username.'@'.$mail_domain;
|
| 103 |
//watchdog('isp_login',"[$mailbox][$login][secret][$org_login]");
|
| 104 |
if (isp_login_check_mailbox($mailbox,$login,$password,$org_login)) return TRUE;
|
| 105 |
watchdog('isp_login',t("Login FAILED: %L",array('%L' => $org_login)));
|
| 106 |
return FALSE;
|
| 107 |
}
|
| 108 |
|
| 109 |
|
| 110 |
/**
|
| 111 |
* Tests the user/password pair on the mailbox
|
| 112 |
*/
|
| 113 |
function isp_login_check_mailbox($mailbox,$login,$password,$org_login) {
|
| 114 |
$mbox = @imap_open($mailbox,$login,$password);
|
| 115 |
if ($mbox) {
|
| 116 |
@imap_close($mbox);
|
| 117 |
|
| 118 |
// without this new users cannot login
|
| 119 |
variable_set('user_register',1);
|
| 120 |
|
| 121 |
watchdog('isp_login',t("Login OK: %L",array('%L' => $org_login)));
|
| 122 |
return TRUE;
|
| 123 |
}
|
| 124 |
return FALSE;
|
| 125 |
}
|
| 126 |
|
| 127 |
|
| 128 |
/**
|
| 129 |
* Implementation of hook_user.
|
| 130 |
*/
|
| 131 |
function isp_login_user($op,$edit,$user,$category = NULL) {
|
| 132 |
switch($op) {
|
| 133 |
case 'insert':
|
| 134 |
user_save($user, array('mail' => $edit['name']));
|
| 135 |
return;
|
| 136 |
case 'login':
|
| 137 |
// TODO: find a way to recover the original user setting instead of force it to 0
|
| 138 |
variable_set('user_register',0);
|
| 139 |
return;
|
| 140 |
}
|
| 141 |
return;
|
| 142 |
}
|
| 143 |
|
| 144 |
|
| 145 |
/**
|
| 146 |
* Implementation of hook_info().
|
| 147 |
*/
|
| 148 |
function isp_login_info($field = 0) {
|
| 149 |
$info['name'] = 'ISP_Login';
|
| 150 |
$info['protocol'] = 'IMAP';
|
| 151 |
|
| 152 |
if ($field) {
|
| 153 |
return $info[$field];
|
| 154 |
}
|
| 155 |
else {
|
| 156 |
return $info;
|
| 157 |
}
|
| 158 |
}
|
| 159 |
|
| 160 |
|
| 161 |
/**
|
| 162 |
* Administrative settings function
|
| 163 |
*/
|
| 164 |
function isp_login_settings() {
|
| 165 |
|
| 166 |
// check if the imap extension is enabled in php
|
| 167 |
if (!function_exists('imap_open')) {
|
| 168 |
form_set_error('isp_login_enabled',t('The php <em>imap extension</em> is disabled in your <em>php.ini</em> file. You must enable it to use the <em>ISP Login</em> module.'));
|
| 169 |
variable_set('isp_login_enabled',0);
|
| 170 |
return system_settings_form(array('isp_login_enabled' => array()));
|
| 171 |
}
|
| 172 |
|
| 173 |
$form['isp_login_enabled'] = array(
|
| 174 |
'#type' => 'radios',
|
| 175 |
'#title' => t("POP or IMAP authentication"),
|
| 176 |
'#default_value' => variable_get('isp_login_enabled',0),
|
| 177 |
'#options' => array(t('Disabled'),t('Enabled')),
|
| 178 |
'#description' => t(
|
| 179 |
'If enabled, your users will be able to authenticate using their e-mail addresses and passwords. On the first login, the corresponding drupal user will be automatically created, if it does not already exists.<br />
|
| 180 |
As a side effect, it changes the <em>!PR</em> option to <em>!OA</em> See the !US page.',
|
| 181 |
array(
|
| 182 |
'!US' => l(t('User settings'),'admin/user/settings'),
|
| 183 |
'!PR' => t('Public registrations'),
|
| 184 |
'!OA' => t('Only site administrators can create new user accounts.')
|
| 185 |
)
|
| 186 |
),
|
| 187 |
);
|
| 188 |
$form['isp_login_servers'] = array(
|
| 189 |
'#type' => 'textarea',
|
| 190 |
'#title' => t('Allowed IMAP and POP3 Servers'),
|
| 191 |
'#default_value' => variable_get('isp_login_servers','127.0.0.1,{localhost:110/pop3/notls},plain'),
|
| 192 |
'#description' => t(
|
| 193 |
'The list of pop/imap servers allowed to act as user authentication sources. Add one server per row, in the form: <strong><em>server_ip,mailbox_def,mode</em></strong>.
|
| 194 |
<ul>
|
| 195 |
<li><strong>server_ip</strong> is the pop/imap server main IP. <strong>Do not</strong> use DNS names here.</li>
|
| 196 |
<li><strong>mailbox_def</strong> is a <em>mailbox</em> definition for the <em>imap_open</em> php function. See the <a href="http://php.net/manual/en/function.imap-open.php"><em>imap_open</em> manual page</a>.</li>
|
| 197 |
<li><strong>mode</strong> must be one of <strong>plain</strong>, <strong>did</strong> or one glue character such as <strong>@</strong>, <strong>*</strong> or <strong>!</strong></li>
|
| 198 |
</ul>
|
| 199 |
Examples:
|
| 200 |
<ul>
|
| 201 |
<li><strong>192.168.10.20,{192.168.10.20:110/pop3/notls},plain</strong> for pop login as <em>username</em>, no encryption.</li>
|
| 202 |
<li><strong>192.168.10.20,{192.168.10.20:993/imap/ssl/novalidate-cert},@</strong> for imap login as <em>username@domain</em>, SSL encryption.</li>
|
| 203 |
<li><strong>192.168.10.20,{192.168.10.20:143/imap/notls},*</strong> for imap login as <em>username*domain</em>, no encryption</li>
|
| 204 |
<li><strong>192.168.10.20,{192.168.10.20:143/imap/notls},did</strong> for imap login as <em>web15_username</em>, no encryption.<br />
|
| 205 |
Retrieves the <em>domain-id</em> (in this example <em>web15_%user%</em>) via a DNS query, and replaces the <em>%user%</em> part with the actual <em>username</em>. For this to work, there must be an appropriate <strong>domain-id IN TXT "webN_%user%"</strong> entry in your DNS, for each virtual domain. It can be used, for example, for <em>ISPConfig</em> servers. (this feature requires php5 or higher)</li>
|
| 206 |
</ul>'
|
| 207 |
)
|
| 208 |
);
|
| 209 |
|
| 210 |
return system_settings_form($form);
|
| 211 |
}
|