1

i tried to setup squid3 with multiple auth_param. Basically, the first choice should be basic_ldap_auth and if this doesnt return OK it should try basic_ncsa_auth with the same values. As far as i know squid doesnt support it however there is the possibility to use "external" ACL

auth_param basic program /usr/lib/squid3/basic_fake_auth
external_acl_type MultAuth %SRC %LOGIN %{Proxy-Authorization} /etc/squid3/multAuth.pl
acl extAuth external MultAuth

my "multAuth.pl"

use URI::Escape;
use MIME::Base64;

$|=1;

   while (<>) {
      ($ip,$user,$auth) = split();

        # Retrieve the password from the authentication header
      $auth = uri_unescape($auth);
      ($type,$authData) = split(/ /, $auth);
      $authString = decode_base64($authData);
      ($username,$password) = split(/:/, $authString);

      # do the authentication and pass results back to Squid.
      $ldap = `/bin/bash auth/ldap.sh`;
      if ($ldap == "OK") {
        print "OK";
      } 
      $ncsa = `/bin/bash auth/ncsa.sh`;
      if ($ncsa == "OK") {
        print "OK";
      } else {
        print "ERR";
      }
}

now i am trying to run with ncsa.sh and ldap.sh the "normal" shell command for these auth methods.

./basic_ldap_auth -R -b "dc=domain,dc=de" -D "CN=Administrator,CN=Users,DC=domain,DC=de" -w "password" -f sAMAccountName=%s -h domain.de
user password

and

./basic_ncsa_auth /etc/squid3/users
user password

Therefor i ran: auth/ncsa.sh

#!/usr/bin/expect
eval spawn [lrange $argv 0 end]
expect ""
send [lindex $argv 1]
send '\r'
expect {
    "OK" {
        echo OK
        exp_continue
    }
    "ERR" {
        echo ERR
    exp_continue
    }
interact

with

./ncsa.sh "/usr/lib/squid3/basic_ncsa_auth /etc/squid3/users" "user password"

and i generate the following error:

couldn't execute "/usr/lib/squid3/basic_ncsa_auth /etc/squid3/users": no such file or directory
while executing
"spawn {/usr/lib/squid3/basic_ncsa_auth /etc/squid3/users} {user password}"
    ("eval" body line 1)
    invoked from within
"eval spawn [lrange $argv 0 end]"
    (file "./ncsa.sh" line 2)

Besides this error, i am not sure how to pass the variables (username & password) forward and i am also not sure how to answer the shell questions like for example the user & pw input for basic_ldap_auth .

Is there a nice way how to solve that? or any other good plan ?

thanks!

1 Answers1

1

FWIW, the following script helped me transition from passwd based to LDAP based authentication.
Contrary to your requirements, my script acts the other way around: It first checks passwd, then LDAP.

#!/usr/bin/env bash

# multiple Squid basic auth checks
# originally posted here: https://github.com/HackerHarry/mSquidAuth
#
# credits
# https://stackoverflow.com/questions/24147067/verify-user-and-password-against-a-file-created-by-htpasswd/40131483
# https://stackoverflow.com/questions/38710483/how-to-stop-ldapsearch1-from-base64-encoding-userpassword-and-other-attributes
#
# requires ldap-utils, openssl and perl
# tested with Squid 4 using a "auth_param basic program /usr/lib/squid/mSquidAuth.sh" line

# authenticate first against squid password file
# if this fails, try LDAP (Active Directory) and also check group membership

# variables
# sLOGFILE=/var/log/squid/mSquidAuth.log
sPWDFILE="/etc/squid/passwd"
sLDAPHOST="ldaps://dc.domain.local:636"
sBASE="DC=domain,DC=local"
sLDS_OPTIONS="-o ldif-wrap=no -o nettimeout=7 -LLL -P3 -x "
sBINDDN="CN=LDAP-read-user,OU=Users,DC=domain,DC=local"
sBINDPW="read-user-password"
sGROUP="Proxy-Users"

# functions
function _grantAccess {
#   echo "access granted - $sUSER" >>$sLOGFILE
    echo "OK"
}

function _denyAccess {
#   echo "access denied - $sUSER" >>$sLOGFILE
    echo "ERR"
}

function _setUserAndPass {
    local sAuth="$1"
    local sOldIFS=$IFS
    IFS=' '
    set -- $sAuth
    IFS=$sOldIFS
    # set it globally
    sUSER="$1"
    sPASS="$2"
}

# loop
while (true); do

read -r sAUTH
sUSER=""
sPASS=""
sSALT=""
sUSERENTRY=""
sHASHEDPW=""
sUSERDN=""
iDNCOUNT=0

if [ -z "$sAUTH" ]; then
#   echo "exiting" >>$sLOGFILE
    exit 0
fi

_setUserAndPass "$sAUTH"

sUSERENTRY=$(grep -E "^${sUSER}:" "$sPWDFILE")
if [ -n "$sUSERENTRY" ]; then
    sSALT=$(echo "$sUSERENTRY" | cut -d$ -f3)
    if [ -n "$sSALT" ]; then
        sHASHEDPW=$(openssl passwd -apr1 -salt "$sSALT" "$sPASS")
        if [ "$sUSERENTRY" = "${sUSER}:${sHASHEDPW}" ]; then
            _grantAccess
            continue
        fi
    fi
fi

# LDAP is next
iDNCOUNT=$(ldapsearch $sLDS_OPTIONS -H "$sLDAPHOST" -D "$sBINDDN" -w "$sBINDPW" -b "$sBASE" "(|(sAMAccountName=${sUSER})(userPrincipalName=${sUSER}))" dn 2>/dev/null | grep -cE 'dn::? ')
if [ $iDNCOUNT != 1 ]; then
    # user needs a unique account
    _denyAccess
    continue
fi
# get user's DN
# we need the extra grep in case we get lines back starting with "# refldap" :/
sUSERDN=$(ldapsearch $sLDS_OPTIONS -H "$sLDAPHOST" -D "$sBINDDN" -w "$sBINDPW" -b "$sBASE" "(|(sAMAccountName=${sUSER})(userPrincipalName=${sUSER}))" dn 2>/dev/null | perl -MMIME::Base64 -n -00 -e 's/\n +//g;s/(?<=:: )(\S+)/decode_base64($1)/eg;print' | grep -E 'dn::? ' | sed -r 's/dn::? //')
# try and bind using that DN to check password validity
# also test if that user is member of a particular group
# backslash in DN needs special treatment
if ldapsearch $sLDS_OPTIONS -H "$sLDAPHOST" -D "$sUSERDN" -w "$sPASS" -b "$sBASE" "name=${sGROUP}" member 2>/dev/null | perl -MMIME::Base64 -n -00 -e 's/\n +//g;s/(?<=:: )(\S+)/decode_base64($1)/eg;print' | grep -q "${sUSERDN/\\/\\\\}"; then
    _grantAccess
    continue
fi
_denyAccess

done
  • It's probably best to add the actual code to this response; that way if the link breaks, users can still access the script you wrote. – franklin Jan 15 '22 at 14:37
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – franklin Jan 15 '22 at 14:37