Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First version to add AD/Kerberos authentication to squid to pfSense 2.3 #34

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 100 additions & 2 deletions www/pfSense-pkg-squid/files/usr/local/pkg/squid.inc
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,8 @@ function squid_write_rcfile() {
$rc = array();
$rc['file'] = 'squid.sh';
$rc['start'] = <<< EOD
KRB5_KTNAME=/usr/local/etc/squid/PROXY.keytab
export KRB5_KTNAME
#/sbin/sysctl net.inet.ip.portrange.reservedhigh=0
if [ -z "`/bin/ps auxw | /usr/bin/grep "[s]quid " | /usr/bin/awk '{print $2}'`" ]; then
{$squid_base}/sbin/squid -f {$squid_conffile_var}
Expand Down Expand Up @@ -496,6 +498,10 @@ function squid_deinstall_command() {

/* remove cronjobs */
squid_install_cron(false);
squid_adk_cron(false);

/* remove adk keytab/krb5secret file */
squid_adk_remove_files();

/* kill all running services */
mwexec('/usr/local/etc/rc.d/sqp_monitor.sh stop');
Expand Down Expand Up @@ -1059,7 +1065,7 @@ function squid_validate_auth($post, &$input_errors) {
unset($num_fields);

$auth_method = $post['auth_method'];
if (($auth_method != 'none') && ($auth_method != 'local') && ($auth_method != 'cp')) {
if (($auth_method != 'none') && ($auth_method != 'local') && ($auth_method != 'cp') && ($auth_method != 'adk')) {
$server = trim($post['auth_server']);
if (empty($server)) {
$input_errors[] = "'Authentication server' is required.";
Expand Down Expand Up @@ -1280,6 +1286,7 @@ EOD;
$conf .= "logfile_rotate {$rotate}\n";
$conf .= "debug_options rotate={$rotate}\n";
squid_install_cron(true);
squid_adk_cron(true);

$conf .= <<< EOD
shutdown_lifetime 3 seconds
Expand Down Expand Up @@ -1847,8 +1854,15 @@ function squid_resync_auth() {
$conf .= "auth_param basic program " . SQUID_LOCALBASE . "/libexec/squid/basic_msnt_auth\n";
squid_resync_msnt();
break;
case 'adk':
$conf .= "auth_param negotiate program " . SQUID_LOCALBASE . "/libexec/squid/negotiate_kerberos_auth\n";
$conf .= "auth_param negotiate children 10\n";
$conf .= "auth_param negotiate keep_alive on\n";
$conf .= "acl password proxy_auth REQUIRED\n";
squid_resync_adk();
break;
}
if ($auth_method != 'cp') {
if (($auth_method != 'cp') or ($auth_method != 'adk')) {
$conf .= <<< EOD
auth_param basic children $processes
auth_param basic realm $prompt
Expand Down Expand Up @@ -1933,6 +1947,90 @@ function squid_resync_msnt() {
chmod(SQUID_CONFBASE . "/msntauth.conf", 0600);
}

/* adk remove keytab/krb5secret if exists */
function squid_adk_remove_files() {
unlink_if_exists(SQUID_CONFBASE . "/PROXY.keytab");
unlink_if_exists("/etc/krb5secret");
}

/* squid adk cron */
function squid_adk_cron($should_install) {
global $config;

if (is_array($config['installedpackages']['squidauth'])) {
$settings = $config['installedpackages']['squidauth']['config'][0];
} else {
$settings = array();
}
$cron_cmd = SQUID_BASE . "/sbin/msktutil --auto-update --verbose --computer-name " . strtolower($config['system']['hostname']);
if ( ($should_install) && ($settings['auth_method'] == 'adk') ) {
log_error("[squid] Adding cronjob for Active Directory authentication ...");
install_cron_job("{$cron_cmd}", true, "0", "0", "1", "*", "*","root");
} else {
log_error("[squid] Removing cronjob for Active Directory authentication ...");
install_cron_job("{$cron_cmd}", false);
}
}

/* Proxy server: Active Directory Kerberos configuration handler */
function squid_resync_adk() {
global $config;

if (is_array($config['installedpackages']['squidauth'])) {
$settings = $config['installedpackages']['squidauth']['config'][0];
} else {
$settings = array();
}

$krb_config = "; http://wiki.squid-cache.org/ConfigExamples/Authenticate/WindowsActiveDirectory\n";
$krb_config .= "[libdefaults]\n";
$krb_config .= " default_realm = " . strtoupper($settings['adk_domain']) . "\n";
$krb_config .= " dns_lookup_kdc = no\n";
$krb_config .= " dns_lookup_realm = no\n";
$krb_config .= " ticket_lifetime = 24h\n";
$krb_config .= " default_keytab_name = " . SQUID_CONFBASE . "/PROXY.keytab\n";
if ($settings['adk_version'] == '2003') {
$krb_config .= "; for Windows 2003\n";
$krb_config .= " default_tgs_enctypes = rc4-hmac des-cbc-crc des-cbc-md5\n";
$krb_config .= " default_tkt_enctypes = rc4-hmac des-cbc-crc des-cbc-md5\n";
$krb_config .= " permitted_enctypes = rc4-hmac des-cbc-crc des-cbc-md5\n";
} elseif ($settings['adk_version'] == '2008') {
$krb_config .= "; for Windows 2008 with AES\n";
$krb_config .= " default_tgs_enctypes = aes256-cts-hmac-sha1-96 rc4-hmac des-cbc-crc des-cbc-md5\n";
$krb_config .= " default_tkt_enctypes = aes256-cts-hmac-sha1-96 rc4-hmac des-cbc-crc des-cbc-md5\n";
$krb_config .= " permitted_enctypes = aes256-cts-hmac-sha1-96 rc4-hmac des-cbc-crc des-cbc-md5\n";
}
$krb_config .= "[realms]\n";
$krb_config .= " " . strtoupper($settings['adk_domain']) . "= {\n";
$krb_config .= " kdc = " . strtolower($settings['adk_dc']) . "\n";
$krb_config .= " admin_server = " . strtolower($settings['adk_dc']) . "\n";
$krb_config .= " default_domain = " . strtolower($settings['adk_domain']) . "\n";
$krb_config .= " }\n";

$krb_config .= "[domain_realm]\n";
$krb_config .= " ." . strtolower($settings['adk_domain']) . " = " . strtoupper($settings['adk_domain']) . "\n";
$krb_config .= " " . strtolower($settings['adk_domain']) . " = " . strtoupper($settings['adk_domain']) . "\n";

file_put_contents("/etc/krb5.conf", $krb_config);
chown("/etc/krb5.conf", SQUID_UID);
chmod("/etc/krb5.conf", 0600);

if ( !file_exists(SQUID_CONFBASE . "/PROXY.keytab") ) {
file_put_contents("/etc/krb5secret", $settings['adk_secret']);
chmod("/etc/krb5secret", 0600);
mwexec("/usr/bin/kinit --password-file=/etc/krb5secret ". $settings['adk_user'] . "@" . strtoupper($settings['adk_domain']));
if ( $settings['adk_version'] == '2003' ) {
mwexec(SQUID_LOCALBASE . '/sbin/msktutil -c -b CN=COMPUTERS -s HTTP -k ' . SQUID_CONFBASE . '/PROXY.keytab --computer-name ' . strtoupper($config['system']['hostname']) . ' --upn HTTP/' . $hostname . ' --server ' . $settings['adk_dc'] . ' --verbose');
} elseif ( $settings['adk_version'] == '2008' ) {
mwexec(SQUID_LOCALBASE . '/sbin/msktutil -c -b CN=COMPUTERS -s HTTP -k ' . SQUID_CONFBASE . '/PROXY.keytab --computer-name ' . strtoupper($config['system']['hostname']) . ' --upn HTTP/' . $hostname . ' --server ' . $settings['adk_dc'] . ' --verbose --enctypes 28');
}
chown(SQUID_CONFBASE . "/PROXY.keytab",SQUID_UID);
chown(SQUID_CONFBASE . "/PROXY.keytab",SQUID_GID);
mwexec("/usr/bin/kdestroy");
unlink("/etc/krb5secret");
}
}

/* Wrapper function to sync whole Squid configuration */
function squid_resync($via_rpc = "no") {
global $config;
Expand Down
46 changes: 45 additions & 1 deletion www/pfSense-pkg-squid/files/usr/local/pkg/squid_auth.xml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
<option><name>RADIUS</name><value>radius</value></option>
<option><name>Captive Portal</name><value>cp</value></option>
<option><name>NT Domain</name><value>msnt</value></option>
<option><name>Active Directory (Kerberos)</name><value>adk</value></option>
</options>
<onchange>on_auth_method_changed()</onchange>
</field>
Expand Down Expand Up @@ -261,6 +262,49 @@
<type>password</type>
<size>20</size>
</field>
<field>
<name>Squid Authentication Active Directory Settings</name>
<type>listtopic</type>
</field>
<field>
<fielddescr>Active Directory Domain</fielddescr>
<fieldname>adk_domain</fieldname>
<description>Enter the Active Directory domain here.</description>
<type>input</type>
<size>60</size>
</field>
<field>
<fielddescr>Active Directory user</fielddescr>
<fieldname>adk_user</fieldname>
<description>Enter the user to use to connect to the LDAP server here.</description>
<type>input</type>
<size>60</size>
</field>
<field>
<fielddescr>Active Directory password</fielddescr>
<fieldname>adk_secret</fieldname>
<description>Enter the password for authentication here.</description>
<type>password</type>
<size>20</size>
</field>
<field>
<fielddescr>Active Directory Domain Controller</fielddescr>
<fieldname>adk_dc</fieldname>
<description>Enter the name of the Domain Controller server here.</description>
<type>input</type>
<size>60</size>
</field>
<field>
<fielddescr>Active Directoy Domain version</fielddescr>
<fieldname>adk_version</fieldname>
<description>Select Active Directory Domain version.</description>
<type>select</type>
<default_value>2</default_value>
<options>
<option><name>2003</name><value>2003</value></option>
<option><name>2008 with AES</name><value>2008</value></option>
</options>
</field>
</fields>
<custom_php_validation_command>
squid_validate_auth($_POST, $input_errors);
Expand All @@ -277,7 +321,7 @@
<custom_php_after_head_command>
<![CDATA[
$transparent_proxy = ($config['installedpackages']['squid']['config'][0]['transparent_proxy'] == 'on');
if ($transparent_proxy and preg_match("/(local|ldap|radius|msnt|ntlm)/", $config['installedpackages']['squidauth']['config'][0]['auth_method'])) {
if ($transparent_proxy and preg_match("/(local|ldap|radius|msnt|ntlm|adk)/", $config['installedpackages']['squidauth']['config'][0]['auth_method'])) {
$input_errors[] = "Authentication cannot be enabled while transparent proxy mode is enabled";
}
squid_print_javascript_auth();
Expand Down
52 changes: 51 additions & 1 deletion www/pfSense-pkg-squid/files/usr/local/pkg/squid_js.inc
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function squid_print_javascript_auth() {
$auth_method = $settingsauth['auth_method'];

// No authentication for transparent proxy
if ($transparent_proxy and preg_match("/(local|ldap|radius|msnt|ntlm)/", $auth_method)) {
if ($transparent_proxy and preg_match("/(local|ldap|radius|msnt|ntlm|adk)/", $auth_method)) {
$javascript = <<< EOD
<script type="text/javascript">
//<![CDATA[
Expand All @@ -73,6 +73,10 @@ function on_auth_method_changed() {
document.iform.auth_ttl.disabled = 1;
document.iform.unrestricted_auth.disabled = 1;
document.iform.no_auth_hosts.disabled = 1;
document.iform.adk_domain.disabled = 1;
document.iform.adk_user.disabled = 1;
document.iform.adk_secret.disabled = 1;
document.iform.adk_version.disabled = 1;
}
//]]>
</script>
Expand Down Expand Up @@ -105,6 +109,10 @@ function on_auth_method_changed() {
document.iform.auth_ttl.disabled = 1;
document.iform.unrestricted_auth.disabled = 1;
document.iform.no_auth_hosts.disabled = 1;
document.iform.adk_domain.disabled = 1;
document.iform.adk_user.disabled = 1;
document.iform.adk_secret.disabled = 1;
document.iform.adk_version.disabled = 1;
} else {
document.iform.auth_prompt.disabled = 0;
document.iform.auth_processes.disabled = 0;
Expand All @@ -126,6 +134,10 @@ function on_auth_method_changed() {
document.iform.ldap_basedomain.disabled = 1;
document.iform.radius_secret.disabled = 1;
document.iform.msnt_secondary.disabled = 1;
document.iform.adk_domain.disabled = 1;
document.iform.adk_user.disabled = 1;
document.iform.adk_secret.disabled = 1;
document.iform.adk_version.disabled = 1;
break;
case 'ldap':
document.iform.auth_server.disabled = 0;
Expand All @@ -139,6 +151,10 @@ function on_auth_method_changed() {
document.iform.radius_secret.disabled = 1;
document.iform.msnt_secondary.disabled = 1;
document.iform.auth_ntdomain.disabled = 1;
document.iform.adk_domain.disabled = 1;
document.iform.adk_user.disabled = 1;
document.iform.adk_secret.disabled = 1;
document.iform.adk_version.disabled = 1;
break;
case 'radius':
document.iform.auth_server.disabled = 0;
Expand All @@ -152,6 +168,10 @@ function on_auth_method_changed() {
document.iform.radius_secret.disabled = 0;
document.iform.msnt_secondary.disabled = 1;
document.iform.auth_ntdomain.disabled = 1;
document.iform.adk_domain.disabled = 1;
document.iform.adk_user.disabled = 1;
document.iform.adk_secret.disabled = 1;
document.iform.adk_version.disabled = 1;
break;
case 'msnt':
document.iform.auth_server.disabled = 0;
Expand All @@ -165,6 +185,10 @@ function on_auth_method_changed() {
document.iform.ldap_basedomain.disabled = 1;
document.iform.radius_secret.disabled = 1;
document.iform.msnt_secondary.disabled = 0;
document.iform.adk_domain.disabled = 1;
document.iform.adk_user.disabled = 1;
document.iform.adk_secret.disabled = 1;
document.iform.adk_version.disabled = 1;
break;
case 'cp':
document.iform.auth_server.disabled = 1;
Expand All @@ -183,6 +207,32 @@ function on_auth_method_changed() {
document.iform.auth_ttl.disabled = 0;
document.iform.unrestricted_auth.disabled = 1;
document.iform.no_auth_hosts.disabled = 1;
document.iform.adk_domain.disabled = 1;
document.iform.adk_user.disabled = 1;
document.iform.adk_secret.disabled = 1;
document.iform.adk_version.disabled = 1;
break;
case 'adk':
document.iform.auth_server.disabled = 1;
document.iform.auth_server_port.disabled = 1;
document.iform.auth_ntdomain.disabled = 1;
document.iform.ldap_user.disabled = 1;
document.iform.ldap_version.disabled = 1;
document.iform.ldap_userattribute.disabled = 1;
document.iform.ldap_filter.disabled = 1;
document.iform.ldap_pass.disabled = 1;
document.iform.ldap_basedomain.disabled = 1;
document.iform.radius_secret.disabled = 1;
document.iform.msnt_secondary.disabled = 1;
document.iform.auth_prompt.disabled = 1;
document.iform.auth_processes.disabled = 0;
document.iform.auth_ttl.disabled = 0;
document.iform.unrestricted_auth.disabled = 1;
document.iform.no_auth_hosts.disabled = 1;
document.iform.adk_domain.disabled = 0;
document.iform.adk_user.disabled = 0;
document.iform.adk_secret.disabled = 0;
document.iform.adk_version.disabled = 0;
break;
}
}
Expand Down