コード例 #1
0
ファイル: my_auth.c プロジェクト: MarianMMX/MarianMMX
static int client_mpvio_write_packet(struct st_plugin_vio *mpv,
                                     const uchar *pkt, size_t pkt_len)
{
    int res;
    MCPVIO_EXT *mpvio= (MCPVIO_EXT*)mpv;

    if (mpvio->packets_written == 0)
    {
        if (mpvio->mysql_change_user)
            res= send_change_user_packet(mpvio, pkt, (int)pkt_len);
        else
            res= send_client_reply_packet(mpvio, pkt, (int)pkt_len);
    }
    else
    {
        NET *net= &mpvio->mysql->net;
        if (mpvio->mysql->thd)
            res= 1; /* no chit-chat in embedded */
        else
            res= my_net_write(net, (char *)pkt, pkt_len) || net_flush(net);
        if (res)
            my_set_error(mpvio->mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
                         ER(CR_SERVER_LOST_EXTENDED),
                         "sending authentication information",
                         errno);
    }
    mpvio->packets_written++;
    return res;
}
コード例 #2
0
ファイル: my_auth.c プロジェクト: MarianMMX/MarianMMX
static int send_client_reply_packet(MCPVIO_EXT *mpvio,
                                    const uchar *data, int data_len)
{
    MYSQL *mysql= mpvio->mysql;
    NET *net= &mysql->net;
    char *buff, *end;
    size_t conn_attr_len= (mysql->options.extension) ?
                          mysql->options.extension->connect_attrs_len : 0;

    /* see end= buff+32 below, fixed size of the packet is 32 bytes */
    buff= my_alloca(33 + USERNAME_LENGTH + data_len + NAME_LEN + NAME_LEN + conn_attr_len + 9);

    mysql->client_flag|= mysql->options.client_flag;
    mysql->client_flag|= CLIENT_CAPABILITIES;

    if (mysql->client_flag & CLIENT_MULTI_STATEMENTS)
        mysql->client_flag|= CLIENT_MULTI_RESULTS;

#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
    if (mysql->options.ssl_key || mysql->options.ssl_cert ||
            mysql->options.ssl_ca || mysql->options.ssl_capath ||
            mysql->options.ssl_cipher)
        mysql->options.use_ssl= 1;
    if (mysql->options.use_ssl)
        mysql->client_flag|= CLIENT_SSL;

    /* if server doesn't support SSL and verification of server certificate
       was set to mandatory, we need to return an error */
    if (mysql->options.use_ssl && !(mysql->server_capabilities & CLIENT_SSL))
    {
        if ((mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) ||
                (mysql->options.extension && (mysql->options.extension->ssl_fp ||
                                              mysql->options.extension->ssl_fp_list)))
        {
            my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
                         ER(CR_SSL_CONNECTION_ERROR),
                         "Server doesn't support SSL");
            goto error;
        }
    }

#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY*/
    if (mpvio->db)
        mysql->client_flag|= CLIENT_CONNECT_WITH_DB;

    /* Remove options that server doesn't support */
    mysql->client_flag= mysql->client_flag &
                        (~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)
                         | mysql->server_capabilities);

#ifndef HAVE_COMPRESS
    mysql->client_flag&= ~CLIENT_COMPRESS;
#endif

    if (mysql->client_flag & CLIENT_PROTOCOL_41)
    {
        /* 4.1 server and 4.1 client has a 32 byte option flag */
        int4store(buff,mysql->client_flag);
        int4store(buff+4, net->max_packet_size);
        buff[8]= (char) mysql->charset->nr;
        bzero(buff+9, 32-9);
        end= buff+32;
    }
    else
    {
        int2store(buff, mysql->client_flag);
        int3store(buff+2, net->max_packet_size);
        end= buff+5;
    }
#ifdef HAVE_OPENSSL
    if (mysql->options.ssl_key ||
            mysql->options.ssl_cert ||
            mysql->options.ssl_ca ||
            mysql->options.ssl_capath ||
            mysql->options.ssl_cipher
#ifdef CRL_IMPLEMENTED
            || (mysql->options.extension &&
                (mysql->options.extension->ssl_crl ||
                 mysql->options.extension->ssl_crlpath))
#endif
       )
        mysql->options.use_ssl= 1;

    if (mysql->options.use_ssl &&
            (mysql->client_flag & CLIENT_SSL))
    {
        SSL *ssl;
        /*
          Send mysql->client_flag, max_packet_size - unencrypted otherwise
          the server does not know we want to do SSL
        */
        if (my_net_write(net, (char*)buff, (size_t) (end-buff)) || net_flush(net))
        {
            my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
                         ER(CR_SERVER_LOST_EXTENDED),
                         "sending connection information to server",
                         errno);
            goto error;
        }

        /* Create SSL */
        if (!(ssl= my_ssl_init(mysql)))
            goto error;

        /* Connect to the server */
        if (my_ssl_connect(ssl))
        {
            SSL_free(ssl);
            goto error;
        }

        if (mysql->options.extension &&
                (mysql->options.extension->ssl_fp || mysql->options.extension->ssl_fp_list))
        {
            if (ma_ssl_verify_fingerprint(ssl))
                goto error;
        }

        if ((mysql->options.ssl_ca || mysql->options.ssl_capath) &&
                (mysql->client_flag & CLIENT_SSL_VERIFY_SERVER_CERT) &&
                my_ssl_verify_server_cert(ssl))
            goto error;
    }
#endif /* HAVE_OPENSSL */

    DBUG_PRINT("info",("Server version = '%s'  capabilites: %lu  status: %u  client_flag: %lu",
                       mysql->server_version, mysql->server_capabilities,
                       mysql->server_status, mysql->client_flag));

    compile_time_assert(MYSQL_USERNAME_LENGTH == USERNAME_LENGTH);

    /* This needs to be changed as it's not useful with big packets */
    if (mysql->user[0])
        strmake(end, mysql->user, USERNAME_LENGTH);
    else
        read_user_name(end);

    /* We have to handle different version of handshake here */
    DBUG_PRINT("info",("user: %s",end));
    end= strend(end) + 1;
    if (data_len)
    {
        if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
        {
            *end++= data_len;
            memcpy(end, data, data_len);
            end+= data_len;
        }
        else
        {
            DBUG_ASSERT(data_len == SCRAMBLE_LENGTH_323 + 1); /* incl. \0 at the end */
            memcpy(end, data, data_len);
            end+= data_len;
        }
    }
    else
        *end++= 0;

    /* Add database if needed */
    if (mpvio->db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
    {
        end= strmake(end, mpvio->db, NAME_LEN) + 1;
        mysql->db= my_strdup(mpvio->db, MYF(MY_WME));
    }

    if (mysql->server_capabilities & CLIENT_PLUGIN_AUTH)
        end= strmake(end, mpvio->plugin->name, NAME_LEN) + 1;

    end= ma_send_connect_attr(mysql, end);

    /* Write authentication package */
    if (my_net_write(net, buff, (size_t) (end-buff)) || net_flush(net))
    {
        my_set_error(mysql, CR_SERVER_LOST, SQLSTATE_UNKNOWN,
                     ER(CR_SERVER_LOST_EXTENDED),
                     "sending authentication information",
                     errno);
        goto error;
    }
    my_afree(buff);
    return 0;

error:
    my_afree(buff);
    return 1;
}
コード例 #3
0
ファイル: my_loaddata.c プロジェクト: dvarnai/simillimum
/* {{{ mysql_handle_local_infile */
my_bool mysql_handle_local_infile(MYSQL *conn, const char *filename)
{
  unsigned int buflen= 4096;
  unsigned int bufread;
  unsigned char *buf= NULL;
  void *info= NULL;
  my_bool result= 1;

  DBUG_ENTER("mysql_handle_local_infile");

  if (!(conn->options.client_flag & CLIENT_LOCAL_FILES)) {
    my_set_error(conn, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, "Load data local infile forbidden");
    /* write empty packet to server */
    my_net_write(&conn->net, "", 0);
    net_flush(&conn->net);
    goto infile_error;
  }

  /* check if all callback functions exist */
  if (!conn->options.local_infile_init || !conn->options.local_infile_end ||
      !conn->options.local_infile_read || !conn->options.local_infile_error)
    mysql_set_local_infile_default(conn);

  /* allocate buffer for reading data */
  buf = (uchar *)my_malloc(buflen, MYF(0));

  /* init handler: allocate read buffer and open file */
  if (conn->options.local_infile_init(&info, filename,
                                      conn->options.local_infile_userdata))
  {
    char tmp_buf[MYSQL_ERRMSG_SIZE];
    int tmp_errno;

    tmp_errno= conn->options.local_infile_error(info, tmp_buf, sizeof(tmp_buf));
    my_set_error(conn, tmp_errno, SQLSTATE_UNKNOWN, tmp_buf);
    my_net_write(&conn->net, "", 0);
    net_flush(&conn->net);
    goto infile_error;
  }

  /* read data */
  while ((bufread= conn->options.local_infile_read(info, (char *)buf, buflen)) > 0)
  {
    if (my_net_write(&conn->net, (char *)buf, bufread))
    {
      my_set_error(conn, CR_SERVER_LOST, SQLSTATE_UNKNOWN, NULL);
      goto infile_error;
    }
  }

  /* send empty packet for eof */
  if (my_net_write(&conn->net, "", 0) || net_flush(&conn->net))
  {
    my_set_error(conn, CR_SERVER_LOST, SQLSTATE_UNKNOWN, NULL);
    goto infile_error;
  }

  /* error during read occured */
  if (bufread < 0)
  {
    char tmp_buf[MYSQL_ERRMSG_SIZE];
    int tmp_errno= conn->options.local_infile_error(info, tmp_buf, sizeof(tmp_buf));
    my_set_error(conn, tmp_errno, SQLSTATE_UNKNOWN, tmp_buf);
    goto infile_error;
  }

  result = 0;

infile_error:
  conn->options.local_infile_end(info);
  my_free((char *)buf, MYF(0));
  DBUG_RETURN(result);
}