Beispiel #1
0
int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
                    const char *data_plugin, const char *db)
{
    const char    *auth_plugin_name;
    auth_plugin_t *auth_plugin;
    MCPVIO_EXT    mpvio;
    ulong		pkt_length;
    int           res;

    /* determine the default/initial plugin to use */
    if (mysql->options.extension && mysql->options.extension->default_auth &&
            mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
    {
        auth_plugin_name= mysql->options.extension->default_auth;
        if (!(auth_plugin= (auth_plugin_t*) mysql_client_find_plugin(mysql,
                           auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
            return 1; /* oops, not found */
    }
    else
    {
        auth_plugin= mysql->server_capabilities & CLIENT_PROTOCOL_41 ?
                     &native_password_client_plugin : &old_password_client_plugin;
        auth_plugin_name= auth_plugin->name;
    }

    mysql->net.last_errno= 0; /* just in case */

    if (data_plugin && strcmp(data_plugin, auth_plugin_name))
    {
        /* data was prepared for a different plugin, don't show it to this one */
        data= 0;
        data_len= 0;
    }

    mpvio.mysql_change_user= data_plugin == 0;
    mpvio.cached_server_reply.pkt= (uchar*)data;
    mpvio.cached_server_reply.pkt_len= data_len;
    mpvio.read_packet= client_mpvio_read_packet;
    mpvio.write_packet= client_mpvio_write_packet;
    mpvio.info= client_mpvio_info;
    mpvio.mysql= mysql;
    mpvio.packets_read= mpvio.packets_written= 0;
    mpvio.db= db;
    mpvio.plugin= auth_plugin;

    res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql);

    compile_time_assert(CR_OK == -1);
    compile_time_assert(CR_ERROR == 0);
    if (res > CR_OK && mysql->net.read_pos[0] != 254)
    {
        /*
          the plugin returned an error. write it down in mysql,
          unless the error code is CR_ERROR and mysql->net.last_errno
          is already set (the plugin has done it)
        */
        if (res > CR_ERROR)
            my_set_error(mysql, res, SQLSTATE_UNKNOWN, 0);
        else if (!mysql->net.last_errno)
            my_set_error(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, 0);
        return 1;
    }

    /* read the OK packet (or use the cached value in mysql->net.read_pos */
    if (res == CR_OK)
        pkt_length= net_safe_read(mysql);
    else /* res == CR_OK_HANDSHAKE_COMPLETE */
        pkt_length= mpvio.last_read_packet_len;

    if (pkt_length == packet_error)
    {
        if (mysql->net.last_errno == CR_SERVER_LOST)
            my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
                         ER(CR_SERVER_LOST_EXTENDED),
                         "reading authorization packet",
                         errno);
        return 1;
    }

    if (mysql->net.read_pos[0] == 254)
    {
        /* The server asked to use a different authentication plugin */
        if (pkt_length == 1)
        {
            /* old "use short scramble" packet */
            auth_plugin_name= old_password_plugin_name;
            mpvio.cached_server_reply.pkt= (uchar*)mysql->scramble_buff;
            mpvio.cached_server_reply.pkt_len= SCRAMBLE_LENGTH + 1;
        }
        else
        {
            /* new "use different plugin" packet */
            uint len;
            auth_plugin_name= (char*)mysql->net.read_pos + 1;
            len= (uint)strlen(auth_plugin_name); /* safe as my_net_read always appends \0 */
            mpvio.cached_server_reply.pkt_len= pkt_length - len - 2;
            mpvio.cached_server_reply.pkt= mysql->net.read_pos + len + 2;
        }

        if (!(auth_plugin= (auth_plugin_t *) mysql_client_find_plugin(mysql,
                           auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
            return 1;

        mpvio.plugin= auth_plugin;
        res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql);

        if (res > CR_OK)
        {
            if (res > CR_ERROR)
                my_set_error(mysql, res, SQLSTATE_UNKNOWN, 0);
            else if (!mysql->net.last_errno)
                my_set_error(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, 0);
            return 1;
        }

        if (res != CR_OK_HANDSHAKE_COMPLETE)
        {
            /* Read what server thinks about out new auth message report */
            if (net_safe_read(mysql) == packet_error)
            {
                if (mysql->net.last_errno == CR_SERVER_LOST)
                    my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
                                 ER(CR_SERVER_LOST_EXTENDED),
                                 "reading final connect information",
                                 errno);
                return 1;
            }
        }
    }
    /*
      net->read_pos[0] should always be 0 here if the server implements
      the protocol correctly
    */
    return mysql->net.read_pos[0] != 0;
}
/* {{{ MARIADB_PVIO *ma_pvio_init */
MARIADB_PVIO *ma_pvio_init(MA_PVIO_CINFO *cinfo)
{
  /* check connection type and load the required plugin.
   * Currently we support the following pvio types:
   *   pvio_socket
   *   pvio_namedpipe
   *   pvio_sharedmed
   */
  const char *pvio_plugins[] = {"pvio_socket", "pvio_npipe", "pvio_shmem"};
  int type;
  MARIADB_PVIO_PLUGIN *pvio_plugin;
  MARIADB_PVIO *pvio= NULL;

  switch (cinfo->type)
  {
    case PVIO_TYPE_UNIXSOCKET:
    case PVIO_TYPE_SOCKET:
      type= 0;
      break;
#ifdef _WIN32
    case PVIO_TYPE_NAMEDPIPE:
      type= 1;
      break;
    case PVIO_TYPE_SHAREDMEM:
      type= 2;
      break;
#endif
    default:
      return NULL;
  }

  if (!(pvio_plugin= (MARIADB_PVIO_PLUGIN *)
                 mysql_client_find_plugin(cinfo->mysql,
                                          pvio_plugins[type], 
                                          MARIADB_CLIENT_PVIO_PLUGIN)))
  {
    /* error already set in mysql_client_find_plugin */
    return NULL;
  }


  if (!(pvio= (MARIADB_PVIO *)calloc(1, sizeof(MARIADB_PVIO)))) 
  {
    PVIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0);
    return NULL;
  }

  /* register error routine and methods */
  pvio->methods= pvio_plugin->methods;
  pvio->set_error= my_set_error;
  pvio->type= cinfo->type;

  /* set timeout to connect timeout - after successfull connect we will set 
   * correct values for read and write */
  if (pvio->methods->set_timeout)
  {
    pvio->methods->set_timeout(pvio, PVIO_CONNECT_TIMEOUT, cinfo->mysql->options.connect_timeout);
    pvio->methods->set_timeout(pvio, PVIO_READ_TIMEOUT, cinfo->mysql->options.connect_timeout);
    pvio->methods->set_timeout(pvio, PVIO_WRITE_TIMEOUT, cinfo->mysql->options.connect_timeout);
  }

  if (!(pvio->cache= calloc(1, PVIO_READ_AHEAD_CACHE_SIZE)))
  {
    PVIO_SET_ERROR(cinfo->mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0);
    free(pvio);
    return NULL;
  }
  pvio->cache_size= 0;
  pvio->cache_pos= pvio->cache;

  return pvio;
}
Beispiel #3
0
/* {{{ ma_open */
MA_FILE *ma_open(const char *location, const char *mode, MYSQL *mysql)
{
  int CodePage= -1;
  FILE *fp= NULL;
  MA_FILE *ma_file= NULL;

  if (!location || !location[0])
    return NULL;
#ifdef HAVE_REMOTEIO
  if (strstr(location, "://"))
    goto remote;
#endif

#ifdef _WIN32
  if (mysql && mysql->charset)
    CodePage= madb_get_windows_cp(mysql->charset->csname);
#endif
  if (CodePage == -1)
  {
    if (!(fp= fopen(location, mode)))
    {
#ifdef _WIN32
      my_errno= GetLastError();
#else
      my_errno= errno;
#endif
      return NULL;
    }
  }
#ifdef _WIN32
  /* See CONC-44: we need to support non ascii filenames too, so we convert
     current character set to wchar_t and try to open the file via _wsopen */
  else
   {
    wchar_t *w_filename= NULL;
    wchar_t *w_mode= NULL;
    int len;
    DWORD Length;

    len= MultiByteToWideChar(CodePage, 0, location, (int)strlen(location), NULL, 0);
    if (!len)
      return NULL;
    if (!(w_filename= (wchar_t *)my_malloc((len + 1) * sizeof(wchar_t), MYF(MY_ZEROFILL))))
    {
      my_set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
      return NULL;
    }
    Length= len;
    len= MultiByteToWideChar(CodePage, 0, location, (int)strlen(location), w_filename, (int)Length);
    if (!len)
    {
      /* todo: error handling */
      my_free(w_filename);
      return NULL;
    }
    len= (int)strlen(mode);
    if (!(w_mode= (wchar_t *)my_malloc((len + 1) * sizeof(wchar_t), MYF(MY_ZEROFILL))))
    {
      my_set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
      my_free(w_filename);
      return NULL;
    }
    Length= len;
    len= MultiByteToWideChar(CodePage, 0, mode, (int)strlen(mode), w_mode, (int)Length);
    if (!len)
    {
      /* todo: error handling */
      my_free(w_filename);
      my_free(w_mode);
      return NULL;
    }
    fp= _wfopen(w_filename, w_mode);
    my_errno= GetLastError();
    my_free(w_filename);
    my_free(w_mode);
  }

#endif
  if (fp)
  {
    ma_file= (MA_FILE *)my_malloc(sizeof(MA_FILE), MYF(0));
    if (!ma_file)
    {
      my_set_error(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
      return NULL;
    }
    ma_file->type= MA_FILE_LOCAL;
    ma_file->ptr= (void *)fp;
  }
  return ma_file;
#ifdef HAVE_REMOTEIO
remote:
  /* check if plugin for remote io is available and try
   * to open location */
  {
    MYSQL mysql;
    if (rio_plugin ||(rio_plugin= (struct st_mysql_client_plugin_REMOTEIO *)
                      mysql_client_find_plugin(&mysql, NULL, MARIADB_CLIENT_REMOTEIO_PLUGIN)))
      return rio_plugin->methods->open(location, mode);
    return NULL;
  }
#endif
}