unable to save custom taxonomy terms in a custom-built metabox in wp-admin

Rather than ‘returning’ on a failure of authentication check, die with an appropriate message:

For example:

  if ( !wp_verify_nonce( $_POST['states_noncename'], plugin_basename( __FILE__ ) ) )
      wp_die("Nonce-check failure");

This will indicate on what check (if any) that you are failing. In most cases, I would advise doing this rather than returning as it gives the user feedback. Obviously, you should not do this for the ‘auto-save’ check – but otherwise, if its clear there is desire to do something, but they are not allowed to, an error message would be preferable to a silent fail.

I think, though that the error lies in the permissions check:

  // Check permissions
  if ( 'post' == $_POST['post_type'] ) 
  {
    if ( !current_user_can( 'edit_page', $post_id ) )
        return;
  }
  else
  {
    if ( !current_user_can( 'edit_post', $post_id ) )
        return;
  }

You check that the post is a post (rather than CPT/page) but then you check if the current user can edit this page. This is likely to return false, because the $post_id refers to a post not a page.

Try swapping the !current_user_cans around. As I mentioned above, the ‘die’ messages should help you debug this.

Finally, and though not related to your problem, you should make sure your functions do not have generatic names: custom_meta_box – you should always prefix them with something unique. If this isn’t something for general release, you might be ok, but it’s just good practise.