The off-spinner finished with 6-102 as the hosts were all out for 292 in their first innings on the stroke of lunch in reply to India's 329.
He was superbly supported by leg-spinner Anil Kumble, who took 3-81.
Sri Lanka skipper Mahela Jayawardene was the lone batsman to defy the Indian attack, top-scoring with a responsible 86 on a spin-friendly track.
The hosts lost their last five wickets for 77 runs after resuming at 215-5.
The hosts lead 1-0 in the three-match series following their win by an innings and 239 runs in the opening Test in Colombo.
India started the day with a double-spin attack, but had to wait for more than an hour to taste success as the Sri Lankan captain and wicket-keeper Prasanna Jayawardene (24) batted cautiously.
Harbhajan, who took four wickets on Friday, completed his 22nd haul of five or more wickets in a Test innings when he had the wicket-keeper caught by Venkatsai Laxman at short-leg.
Kumble got his first wicket of the series when he re