~ubuntu-branches/ubuntu/maverick/mysql-5.1/maverick-proposed

« back to all changes in this revision

Viewing changes to sql/sql_acl.cc

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-02-22 14:16:05 UTC
  • mto: This revision was merged to the branch mainline in revision 20.
  • Revision ID: package-import@ubuntu.com-20120222141605-nxlu9yzc6attylc2
Tags: upstream-5.1.61
ImportĀ upstreamĀ versionĀ 5.1.61

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2003 MySQL AB
 
1
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
2
2
 
3
3
   This program is free software; you can redistribute it and/or modify
4
4
   it under the terms of the GNU General Public License as published by
194
194
                             const char *ip);
195
195
static my_bool acl_load(THD *thd, TABLE_LIST *tables);
196
196
static my_bool grant_load(THD *thd, TABLE_LIST *tables);
 
197
static inline void get_grantor(THD *thd, char* grantor);
197
198
 
198
199
/*
199
200
  Convert scrambled password to binary form, according to scramble type, 
1592
1593
  /* Buffer should be extended when password length is extended. */
1593
1594
  char buff[512];
1594
1595
  ulong query_length;
 
1596
  bool save_binlog_row_based;
1595
1597
  uint new_password_len= (uint) strlen(new_password);
1596
1598
  bool result= 1;
1597
1599
  DBUG_ENTER("change_password");
1627
1629
  if (!(table= open_ltable(thd, &tables, TL_WRITE, 0)))
1628
1630
    DBUG_RETURN(1);
1629
1631
 
 
1632
  /*
 
1633
    This statement will be replicated as a statement, even when using
 
1634
    row-based replication.  The flag will be reset at the end of the
 
1635
    statement.
 
1636
  */
 
1637
  if ((save_binlog_row_based= thd->current_stmt_binlog_row_based))
 
1638
    thd->clear_current_stmt_binlog_row_based();
 
1639
 
1630
1640
  VOID(pthread_mutex_lock(&acl_cache->lock));
1631
1641
  ACL_USER *acl_user;
1632
1642
  if (!(acl_user= find_acl_user(host, user, TRUE)))
1652
1662
  result= 0;
1653
1663
  if (mysql_bin_log.is_open())
1654
1664
  {
1655
 
    query_length=
1656
 
      my_sprintf(buff,
1657
 
                 (buff,"SET PASSWORD FOR '%-.120s'@'%-.120s'='%-.120s'",
1658
 
                  acl_user->user ? acl_user->user : "",
1659
 
                  acl_user->host.hostname ? acl_user->host.hostname : "",
1660
 
                  new_password));
 
1665
    query_length= sprintf(buff, "SET PASSWORD FOR '%-.120s'@'%-.120s'='%-.120s'",
 
1666
                          acl_user->user ? acl_user->user : "",
 
1667
                          acl_user->host.hostname ? acl_user->host.hostname : "",
 
1668
                          new_password);
1661
1669
    thd->clear_error();
1662
1670
    result= thd->binlog_query(THD::MYSQL_QUERY_TYPE, buff, query_length,
1663
1671
                              FALSE, FALSE, 0);
1664
1672
  }
1665
1673
end:
1666
1674
  close_thread_tables(thd);
 
1675
 
 
1676
  /* Restore the state of binlog format */
 
1677
  DBUG_ASSERT(!thd->current_stmt_binlog_row_based);
 
1678
  if (save_binlog_row_based)
 
1679
    thd->set_current_stmt_binlog_row_based();
 
1680
 
1667
1681
  DBUG_RETURN(result);
1668
1682
}
1669
1683
 
1956
1970
    */
1957
1971
    else if (!password_len && no_auto_create)
1958
1972
    {
1959
 
      my_error(ER_PASSWORD_NO_MATCH, MYF(0), combo.user.str, combo.host.str);
 
1973
      my_error(ER_PASSWORD_NO_MATCH, MYF(0));
1960
1974
      goto end;
1961
1975
    }
1962
1976
    else if (!can_create_user)
1963
1977
    {
1964
 
      my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0),
1965
 
               thd->security_ctx->user, thd->security_ctx->host_or_ip);
 
1978
      my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0));
1966
1979
      goto end;
1967
1980
    }
1968
1981
    old_row_exists = 0;
2704
2717
  DBUG_RETURN(result);
2705
2718
}
2706
2719
 
 
2720
static inline void get_grantor(THD *thd, char *grantor)
 
2721
{
 
2722
  const char *user= thd->security_ctx->user;
 
2723
  const char *host= thd->security_ctx->host_or_ip;
 
2724
 
 
2725
#if defined(HAVE_REPLICATION)
 
2726
  if (thd->slave_thread && thd->has_invoker())
 
2727
  {
 
2728
    user= thd->get_invoker_user().str;
 
2729
    host= thd->get_invoker_host().str;
 
2730
  }
 
2731
#endif
 
2732
  strxmov(grantor, user, "@", host, NullS);
 
2733
}
2707
2734
 
2708
2735
static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
2709
2736
                               TABLE *table, const LEX_USER &combo,
2718
2745
  uchar user_key[MAX_KEY_LENGTH];
2719
2746
  DBUG_ENTER("replace_table_table");
2720
2747
 
2721
 
  strxmov(grantor, thd->security_ctx->user, "@",
2722
 
          thd->security_ctx->host_or_ip, NullS);
2723
 
 
 
2748
  get_grantor(thd, grantor);
2724
2749
  /*
2725
2750
    The following should always succeed as new users are created before
2726
2751
    this function is called!
2850
2875
    DBUG_RETURN(-1);
2851
2876
  }
2852
2877
 
2853
 
  strxmov(grantor, thd->security_ctx->user, "@",
2854
 
          thd->security_ctx->host_or_ip, NullS);
2855
 
 
 
2878
  get_grantor(thd, grantor);
2856
2879
  /*
2857
2880
    New users are created before this function is called.
2858
2881
 
5353
5376
}
5354
5377
 
5355
5378
 
5356
 
/*
 
5379
/**
5357
5380
  Handle an in-memory privilege structure.
5358
5381
 
5359
 
  SYNOPSIS
5360
 
    handle_grant_struct()
5361
 
    struct_no                   The number of the structure to handle (0..3).
5362
 
    drop                        If user_from is to be dropped.
5363
 
    user_from                   The the user to be searched/dropped/renamed.
5364
 
    user_to                     The new name for the user if to be renamed,
5365
 
                                NULL otherwise.
 
5382
  @param struct_no  The number of the structure to handle (0..4).
 
5383
  @param drop       If user_from is to be dropped.
 
5384
  @param user_from  The the user to be searched/dropped/renamed.
 
5385
  @param user_to    The new name for the user if to be renamed, NULL otherwise.
5366
5386
 
5367
 
  DESCRIPTION
 
5387
  @note
5368
5388
    Scan through all elements in an in-memory grant structure and apply
5369
5389
    the requested operation.
5370
5390
    Delete from grant structure if drop is true.
5374
5394
    0 acl_users
5375
5395
    1 acl_dbs
5376
5396
    2 column_priv_hash
5377
 
    3 procs_priv_hash
 
5397
    3 proc_priv_hash
 
5398
    4 func_priv_hash
5378
5399
 
5379
 
  RETURN
5380
 
    > 0         At least one element matched.
5381
 
    0           OK, but no element matched.
5382
 
    -1          Wrong arguments to function
 
5400
  @retval > 0  At least one element matched.
 
5401
  @retval 0    OK, but no element matched.
 
5402
  @retval -1   Wrong arguments to function.
5383
5403
*/
5384
5404
 
5385
5405
static int handle_grant_struct(uint struct_no, bool drop,
5393
5413
  ACL_USER *acl_user= NULL;
5394
5414
  ACL_DB *acl_db= NULL;
5395
5415
  GRANT_NAME *grant_name= NULL;
 
5416
  HASH *grant_name_hash= NULL;
5396
5417
  DBUG_ENTER("handle_grant_struct");
5397
5418
  DBUG_PRINT("info",("scan struct: %u  search: '%s'@'%s'",
5398
5419
                     struct_no, user_from->user.str, user_from->host.str));
5412
5433
    break;
5413
5434
  case 2:
5414
5435
    elements= column_priv_hash.records;
 
5436
    grant_name_hash= &column_priv_hash;
5415
5437
    break;
5416
5438
  case 3:
5417
5439
    elements= proc_priv_hash.records;
 
5440
    grant_name_hash= &proc_priv_hash;
 
5441
    break;
 
5442
  case 4:
 
5443
    elements= func_priv_hash.records;
 
5444
    grant_name_hash= &func_priv_hash;
5418
5445
    break;
5419
5446
  default:
5420
5447
    return -1;
5444
5471
      break;
5445
5472
 
5446
5473
    case 2:
5447
 
      grant_name= (GRANT_NAME*) hash_element(&column_priv_hash, idx);
5448
 
      user= grant_name->user;
5449
 
      host= grant_name->host.hostname;
5450
 
      break;
5451
 
 
5452
5474
    case 3:
5453
 
      grant_name= (GRANT_NAME*) hash_element(&proc_priv_hash, idx);
 
5475
    case 4:
 
5476
      grant_name= (GRANT_NAME*) hash_element(grant_name_hash, idx);
5454
5477
      user= grant_name->user;
5455
5478
      host= grant_name->host.hostname;
5456
5479
      break;
 
5480
 
5457
5481
    default:
5458
 
      assert(0);
 
5482
      MY_ASSERT_UNREACHABLE();
5459
5483
    }
5460
5484
    if (! user)
5461
5485
      user= "";
5483
5507
        break;
5484
5508
 
5485
5509
      case 2:
5486
 
        hash_delete(&column_priv_hash, (uchar*) grant_name);
5487
 
        break;
5488
 
 
5489
5510
      case 3:
5490
 
        hash_delete(&proc_priv_hash, (uchar*) grant_name);
 
5511
      case 4:
 
5512
        hash_delete(grant_name_hash, (uchar*) grant_name);
5491
5513
        break;
5492
5514
      }
5493
5515
      elements--;
 
5516
      /*
 
5517
        - If we are iterating through an array then we just have moved all
 
5518
          elements after the current element one position closer to its head.
 
5519
          This means that we have to take another look at the element at
 
5520
          current position as it is a new element from the array's tail.
 
5521
        - If we are iterating through a hash the current element was replaced
 
5522
          with one of elements from the tail. So we also have to take a look
 
5523
          at the new element in current position.
 
5524
          Note that in our HASH implementation hash_delete() won't move any
 
5525
          elements with position after current one to position before the
 
5526
          current (i.e. from the tail to the head), so it is safe to continue
 
5527
          iteration without re-starting.
 
5528
      */
5494
5529
      idx--;
5495
5530
    }
5496
5531
    else if ( user_to )
5508
5543
 
5509
5544
      case 2:
5510
5545
      case 3:
5511
 
        /* 
5512
 
          Update the grant structure with the new user name and
5513
 
          host name
5514
 
        */
5515
 
        grant_name->set_user_details(user_to->host.str, grant_name->db,
5516
 
                                     user_to->user.str, grant_name->tname,
5517
 
                                     TRUE);
5518
 
 
5519
 
        /*
5520
 
          Since username is part of the hash key, when the user name
5521
 
          is renamed, the hash key is changed. Update the hash to
5522
 
          ensure that the position matches the new hash key value
5523
 
        */
5524
 
        hash_update(&column_priv_hash, (uchar*) grant_name,
5525
 
                    (uchar*) grant_name->hash_key, grant_name->key_length);
5526
 
        break;
 
5546
      case 4:
 
5547
        {
 
5548
          /*
 
5549
            Save old hash key and its length to be able properly update
 
5550
            element position in hash.
 
5551
          */
 
5552
          char *old_key= grant_name->hash_key;
 
5553
          size_t old_key_length= grant_name->key_length;
 
5554
 
 
5555
          /*
 
5556
            Update the grant structure with the new user name and host name.
 
5557
          */
 
5558
          grant_name->set_user_details(user_to->host.str, grant_name->db,
 
5559
                                       user_to->user.str, grant_name->tname,
 
5560
                                       TRUE);
 
5561
 
 
5562
          /*
 
5563
            Since username is part of the hash key, when the user name
 
5564
            is renamed, the hash key is changed. Update the hash to
 
5565
            ensure that the position matches the new hash key value
 
5566
          */
 
5567
          hash_update(grant_name_hash, (uchar*) grant_name, (uchar*) old_key,
 
5568
                      old_key_length);
 
5569
          /*
 
5570
            hash_update() operation could have moved element from the tail
 
5571
            of the hash to the current position. So we need to take a look
 
5572
            at the element in current position once again.
 
5573
            Thanks to the fact that hash_update() for our HASH implementation
 
5574
            won't move any elements from the tail of the hash to the positions
 
5575
            before the current one (a.k.a. head) it is safe to continue
 
5576
            iteration without restarting.
 
5577
          */
 
5578
          idx--;
 
5579
          break;
 
5580
        }
5527
5581
      }
5528
5582
    }
5529
5583
    else
5609
5663
    }
5610
5664
  }
5611
5665
 
5612
 
  /* Handle procedures table. */
 
5666
  /* Handle stored routines table. */
5613
5667
  if ((found= handle_grant_table(tables, 4, drop, user_from, user_to)) < 0)
5614
5668
  {
5615
5669
    /* Handle of table failed, don't touch in-memory array. */
5626
5680
      if (! drop && ! user_to)
5627
5681
        goto end;
5628
5682
    }
 
5683
    /* Handle funcs array. */
 
5684
    if (((handle_grant_struct(4, drop, user_from, user_to) && ! result) ||
 
5685
         found) && ! result)
 
5686
    {
 
5687
      result= 1; /* At least one record/element found. */
 
5688
      /* If search is requested, we do not need to search further. */
 
5689
      if (! drop && ! user_to)
 
5690
        goto end;
 
5691
    }
5629
5692
  }
5630
5693
 
5631
5694
  /* Handle tables table. */
5692
5755
{
5693
5756
  int result;
5694
5757
  String wrong_users;
5695
 
  ulong sql_mode;
5696
5758
  LEX_USER *user_name, *tmp_user_name;
5697
5759
  List_iterator <LEX_USER> user_list(list);
5698
5760
  TABLE_LIST tables[GRANT_TABLES];
5739
5801
    }
5740
5802
 
5741
5803
    some_users_created= TRUE;
5742
 
    sql_mode= thd->variables.sql_mode;
5743
5804
    if (replace_user_table(thd, tables[0].table, *user_name, 0, 0, 1, 0))
5744
5805
    {
5745
5806
      append_user(&wrong_users, user_name);