Zcash - where are treestates stored?
You are correct that the Sprout commitment tree root / anchor is not stored in the block header. It is calculated by each node when a block arrives, and is stored in the block index.

The Sapling commitment tree root is stored in the block header (in what was the hashReserved field); nodes check this against the block contents and reject blocks with an invalid root in the header. This will make shielded address support significantly easier to implement for light clients.

The mappings from Sprout and Sapling tree roots to the IncrementalMerkleTrees themselves are stored in the coins database, and can be accessed wherever you have a CCoinsView.