@@ -5751,6 +5751,118 @@ bool check_global_access(THD *thd, ulong want_access)
5751
5751
#endif
5752
5752
}
5753
5753
5754
+
5755
+ /* *
5756
+ Checks foreign key's parent table access.
5757
+
5758
+ @param thd [in] Thread handler
5759
+ @param create_info [in] Create information (like MAX_ROWS, ENGINE or
5760
+ temporary table flag)
5761
+ @param alter_info [in] Initial list of columns and indexes for the
5762
+ table to be created
5763
+
5764
+ @retval
5765
+ false ok.
5766
+ @retval
5767
+ true error or access denied. Error is sent to client in this case.
5768
+ */
5769
+ bool check_fk_parent_table_access (THD *thd,
5770
+ HA_CREATE_INFO *create_info,
5771
+ Alter_info *alter_info)
5772
+ {
5773
+ Key *key;
5774
+ List_iterator<Key> key_iterator (alter_info->key_list );
5775
+ handlerton *db_type= create_info->db_type ? create_info->db_type :
5776
+ ha_default_handlerton (thd);
5777
+
5778
+ // Return if engine does not support Foreign key Constraint.
5779
+ if (!ha_check_storage_engine_flag (db_type, HTON_SUPPORTS_FOREIGN_KEYS))
5780
+ return false ;
5781
+
5782
+ while ((key= key_iterator++))
5783
+ {
5784
+ if (key->type == Key::FOREIGN_KEY)
5785
+ {
5786
+ TABLE_LIST parent_table;
5787
+ bool is_qualified_table_name;
5788
+ Foreign_key *fk_key= (Foreign_key *)key;
5789
+ LEX_STRING db_name;
5790
+ LEX_STRING table_name= { fk_key->ref_table .str ,
5791
+ fk_key->ref_table .length };
5792
+ const ulong privileges= (SELECT_ACL | INSERT_ACL | UPDATE_ACL |
5793
+ DELETE_ACL | REFERENCES_ACL);
5794
+
5795
+ // Check if tablename is valid or not.
5796
+ DBUG_ASSERT (table_name.str != NULL );
5797
+ if (check_table_name (table_name.str , table_name.length , false ))
5798
+ {
5799
+ my_error (ER_WRONG_TABLE_NAME, MYF (0 ), table_name.str );
5800
+ return true ;
5801
+ }
5802
+
5803
+ if (fk_key->ref_db .str )
5804
+ {
5805
+ is_qualified_table_name= true ;
5806
+ db_name.str = (char *) thd->memdup (fk_key->ref_db .str ,
5807
+ fk_key->ref_db .length +1 );
5808
+ db_name.length = fk_key->ref_db .length ;
5809
+
5810
+ // Check if database name is valid or not.
5811
+ if (fk_key->ref_db .str && check_and_convert_db_name (&db_name, false ))
5812
+ return true ;
5813
+ }
5814
+ else if (thd->lex ->copy_db_to (&db_name.str , &db_name.length ))
5815
+ return true ;
5816
+ else
5817
+ is_qualified_table_name= false ;
5818
+
5819
+ // if lower_case_table_names is set then convert tablename to lower case.
5820
+ if (lower_case_table_names)
5821
+ {
5822
+ table_name.str = (char *) thd->memdup (fk_key->ref_table .str ,
5823
+ fk_key->ref_table .length +1 );
5824
+ table_name.length = my_casedn_str (files_charset_info, table_name.str );
5825
+ }
5826
+
5827
+ parent_table.init_one_table (db_name.str , db_name.length ,
5828
+ table_name.str , table_name.length ,
5829
+ table_name.str , TL_IGNORE);
5830
+
5831
+ /*
5832
+ Check if user has any of the "privileges" at table level on
5833
+ "parent_table".
5834
+ Having privilege on any of the parent_table column is not
5835
+ enough so checking whether user has any of the "privileges"
5836
+ at table level only here.
5837
+ */
5838
+ if (check_some_access (thd, privileges, &parent_table) ||
5839
+ parent_table.grant .want_privilege )
5840
+ {
5841
+ if (is_qualified_table_name)
5842
+ {
5843
+ const size_t qualified_table_name_len= NAME_LEN + 1 + NAME_LEN + 1 ;
5844
+ char *qualified_table_name= (char *) thd->alloc (qualified_table_name_len);
5845
+
5846
+ my_snprintf (qualified_table_name, qualified_table_name_len, " %s.%s" ,
5847
+ db_name.str , table_name.str );
5848
+ table_name.str = qualified_table_name;
5849
+ }
5850
+
5851
+ my_error (ER_TABLEACCESS_DENIED_ERROR, MYF (0 ),
5852
+ " REFERENCES" ,
5853
+ thd->security_ctx ->priv_user ,
5854
+ thd->security_ctx ->host_or_ip ,
5855
+ table_name.str );
5856
+
5857
+ return true ;
5858
+ }
5859
+ }
5860
+ }
5861
+
5862
+ return false ;
5863
+ }
5864
+
5865
+
5754
5866
/* ***************************************************************************
5755
5867
Check stack size; Send error if there isn't enough stack to continue
5756
5868
****************************************************************************/
@@ -7803,8 +7915,11 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
7803
7915
if (check_table_access (thd, SELECT_ACL, tables, FALSE , UINT_MAX, FALSE ))
7804
7916
goto err;
7805
7917
}
7806
- error= FALSE ;
7807
7918
7919
+ if (check_fk_parent_table_access (thd, &lex->create_info , &lex->alter_info ))
7920
+ goto err;
7921
+
7922
+ error= FALSE ;
7808
7923
err:
7809
7924
DBUG_RETURN (error);
7810
7925
}
0 commit comments