By stumps Bangladesh, who trailed Sri Lanka by 106 after the first innings, were 158 for four wickets - an overall lead of 52.
Mominul Haque scored an attractive half-century in the first innings and was unbeaten on 36 second time around with Mushfiqur Rahim on seven.
Both batsmen would have been out before the close had the Sri Lankan fielders been sharper.
Mominul was put down at mid-on by Nuwan Kulasekara when he was on 30 and Angelo Mathews missed Mushfiqur at slip also off Herath, who ended the day with figures of three for 45.
"It would have been brilliant to have them five down," said Sri Lanka's Kumar Sangakkara. "We had the opportunities, though a close decision also didn't go our way towards the end.
"We've got ourselves to blame, one was quite an easy chance and one not so easy."
Mohammad Ashraful became Herath's first victim when he was bowled for four by a quicker delivery in the second over after tea when his off stump was sent tumbling.
A stand of 47 followed between Jahurul Islam and Mominul that carried Bangladesh to 143-2 before Herath struck twice in his 19th over.
He changed the complexion of the game by having Jahurul stumped by Dinesh Chandimal for 48 when the batsman lost his patience and charged up the wicket.
On the next ball, Mahmudullah was beaten by a tossed-up delivery from Herath and had his off stump knocked out.
Mushfiqur survived the hat-trick ball and was lucky to be there at the close.
Openers Tamim Iqbal and Jahurul provided a strong start to help Bangladesh reach 93 for one at tea.
On a surface which had flattened out at the R. Premadasa Stadium, Tamim and Jahurul batted confidently.
Tamim, who missed the first Test through injury, was the aggressor in the partnership, reaching his fifty off 67 balls with the help of one six and four fours.
He was dropped on 12 when Suranga Lakmal failed to hold a knee-high return catch.
A bowling change by Sri Lanka captain Angelo Mathews brought about the dismissal of Tamim, who tried to cut a ball from Shaminda Eranga but only succeeded in chopping it on to his stumps to depart for 59.
Earlier, Sri Lanka resumed on 294 for six and a lot depended on how long Sangakkara could bat on to give the hosts a healthy first-innings lead.
Starting the day on 127, Sangakkara had added 12 runs to his overnight score when he went for a drive off Abul Hasan and, after a long delay, the third umpire ruled him out caught behind by Mushfiqur.
Sangakkara scored 139 off 289 balls and hit 11 fours in his third century in this series.
Sohag Gazi bowled Herath for three and dismissed Kulasekara for 22 when the batsman gave Mushfiqur his fifth catch of the innings as the spinner finished with figures of three for 111.
Mahmudullah then removed Shaminda Eranga (15) as Sri Lanka were all out for 346 in their first innings.