@@ -1306,8 +1306,10 @@ def bind_simple(auth)
13061306 #
13071307 # If ruby-sasl is avaiable, :host is used to setup digest-url and defaults to
13081308 # connection hostname. Also, for some mechs, the :username and :password are used.
1309+ # :secure_layer define if SASL should atempt to use secure layer (similar to SSL)
13091310 # :initial_credential and :challenge_response are optional and filled by
1310- # setup_auth_sasl.
1311+ # setup_auth_sasl. Extra preferences for sasl library like :gss_opts be defined as
1312+ # a hash in :sasl_opts.
13111313 #
13121314 # If ruby-sasl is not avaiable, :initial_credential and :challenge_response
13131315 # are required.
@@ -1353,36 +1355,54 @@ def bind_sasl(auth)
13531355 @conn . write request_pkt
13541356
13551357 ( be = @conn . read_ber ( Net ::LDAP ::AsnSyntax ) and pdu = Net ::LDAP ::PDU . new ( be ) ) or raise Net ::LDAP ::LdapError , "no bind result"
1356- if securelayer_wrapper
1357- $stderr. puts "secure lay"
1358- @conn = self . class . wrap_with_sasl ( @conn , securelayer_wrapper )
1358+
1359+ case pdu . result_code
1360+ when 14 # SASLBindInProgress
1361+ cred = chall . call ( pdu . result_server_sasl_creds , :challenge )
1362+ when 0 # Authenticated
1363+ securelayer_wrapper = chall . call ( pdu . result_server_sasl_creds , :success )
1364+ if securelayer_wrapper
1365+ @conn = self . class . wrap_with_sasl ( @conn , securelayer_wrapper )
1366+ end
1367+ return pdu
1368+ else # Error
1369+ chall . call ( pdu . result_server_sasl_creds , :failure )
1370+ return pdu
13591371 end
1360- return pdu unless pdu . result_code == 14 # saslBindInProgress
1361- raise Net ::LDAP ::LdapError , "sasl-challenge overflow" if ( ( n += 1 ) > MaxSaslChallenges )
13621372
1363- ( cred , securelayer_wrapper ) = chall . call ( pdu . result_server_sasl_creds )
1373+ raise Net :: LDAP :: LdapError , "sasl-challenge overflow" if ( ( n += 1 ) > MaxSaslChallenges )
13641374 }
13651375
13661376 raise Net ::LDAP ::LdapError , "why are we here?"
13671377 end
13681378 private :bind_sasl
13691379
1370- SASL_SERVICE_NAME = "ldap"
1380+ SASL_SERVICE_TYPE = "ldap"
13711381
13721382 def self . setup_auth_sasl ( auth )
13731383 raise Net ::LDAP ::LdapError , "SASL library (gem ruby-sasl) is unavailable" unless Net ::LDAP ::HasSASL
13741384 raise Net ::LDAP ::LdapError , "Invalid binding information. auth[:host] is required" unless auth . include? ( :host )
13751385
1376- pref = SASL ::Preferences . new (
1377- :digest_uri => "#{ SASL_SERVICE_NAME } /#{ auth [ :host ] } " ,
1378- :username => auth [ :username ] || auth [ :dn ] ,
1379- :password => auth [ :password ] ,
1380- )
1381- sasl = SASL . new_mechanism ( auth [ :mechanism ] , pref )
1382-
1383- challenge_response = Proc . new do |cred |
1384- response = sasl . receive ( "challenge" , cred )
1385- response [ 1 ]
1386+ opts = { :digest_uri => "#{ SASL_SERVICE_TYPE } /#{ auth [ :host ] } " ,
1387+ :username => auth [ :username ] || auth [ :dn ] ,
1388+ :password => auth [ :password ] ,
1389+ :secure_layer => auth [ :secure_layer ] ,
1390+ }
1391+ opts . merge! ( auth [ :sasl_opts ] ) if auth . include? :sasl_opts
1392+
1393+ sasl = SASL . new_mechanism ( auth [ :mechanism ] , SASL ::Preferences . new ( opts ) )
1394+
1395+ challenge_response = Proc . new do |cred , result |
1396+ case result
1397+ when :challenge
1398+ response = sasl . receive ( "challenge" , cred )
1399+ response [ 1 ]
1400+ when :success
1401+ response = sasl . receive ( "success" , cred )
1402+ response [ 1 ] if response
1403+ when :failure
1404+ response = sasl . receive ( "failure" , cred )
1405+ end
13861406 end
13871407
13881408 initial_credential = sasl . start [ 1 ]
0 commit comments