Coverage Report

Created: 2025-01-09 07:36

/src/osquery/osquery/sql/sqlite_util.cpp
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * Copyright (c) 2014-present, The osquery authors
3
 *
4
 * This source code is licensed as defined by the LICENSE file found in the
5
 * root directory of this source tree.
6
 *
7
 * SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
8
 */
9
10
#include "osquery/sql/sqlite_util.h"
11
#include "osquery/sql/virtual_table.h"
12
13
#include <osquery/core/plugins/sql.h>
14
15
#include <osquery/utils/conversions/castvariant.h>
16
17
#include <osquery/core/core.h>
18
#include <osquery/core/flags.h>
19
#include <osquery/core/shutdown.h>
20
#include <osquery/logger/logger.h>
21
#include <osquery/registry/registry_factory.h>
22
#include <osquery/sql/sql.h>
23
24
#include <osquery/utils/conversions/split.h>
25
26
#include <boost/lexical_cast.hpp>
27
28
namespace osquery {
29
30
CLI_FLAG(string,
31
         disable_tables,
32
         "",
33
         "Comma-delimited list of table names to be disabled");
34
35
CLI_FLAG(string,
36
         enable_tables,
37
         "",
38
         "Comma-delimited list of table names to be enabled");
39
40
FLAG(string, nullvalue, "", "Set string for NULL values, default ''");
41
42
using OpReg = QueryPlanner::Opcode::Register;
43
44
using SQLiteDBInstanceRef = std::shared_ptr<SQLiteDBInstance>;
45
46
/**
47
 * @brief A map of SQLite status codes to their corresponding message string
48
 *
49
 * Details of this map are defined at: http://www.sqlite.org/c3ref/c_abort.html
50
 */
51
// clang-format off
52
const std::map<int, std::string> kSQLiteReturnCodes = {
53
    {0, "SQLITE_OK"},        {1, "SQLITE_ERROR"},       {2, "SQLITE_INTERNAL"},
54
    {3, "SQLITE_PERM"},      {4, "SQLITE_ABORT"},       {5, "SQLITE_BUSY"},
55
    {6, "SQLITE_LOCKED"},    {7, "SQLITE_NOMEM"},       {8, "SQLITE_READONLY"},
56
    {9, "SQLITE_INTERRUPT"}, {10, "SQLITE_IOERR"},      {11, "SQLITE_CORRUPT"},
57
    {12, "SQLITE_NOTFOUND"}, {13, "SQLITE_FULL"},       {14, "SQLITE_CANTOPEN"},
58
    {15, "SQLITE_PROTOCOL"}, {16, "SQLITE_EMPTY"},      {17, "SQLITE_SCHEMA"},
59
    {18, "SQLITE_TOOBIG"},   {19, "SQLITE_CONSTRAINT"}, {20, "SQLITE_MISMATCH"},
60
    {21, "SQLITE_MISUSE"},   {22, "SQLITE_NOLFS"},      {23, "SQLITE_AUTH"},
61
    {24, "SQLITE_FORMAT"},   {25, "SQLITE_RANGE"},      {26, "SQLITE_NOTADB"},
62
    {27, "SQLITE_NOTICE"},   {28, "SQLITE_WARNING"},    {100, "SQLITE_ROW"},
63
    {101, "SQLITE_DONE"},
64
};
65
66
const std::map<std::string, std::string> kMemoryDBSettings = {
67
    {"synchronous", "OFF"},      {"count_changes", "OFF"},
68
    {"default_temp_store", "0"}, {"auto_vacuum", "FULL"},
69
    {"journal_mode", "OFF"},     {"cache_size", "0"},
70
    {"page_count", "0"},
71
};
72
// clang-format on
73
74
#define OpComparator(x)                                                        \
75
  { x, QueryPlanner::Opcode(OpReg::P2, INTEGER_TYPE) }
76
#define Arithmetic(x)                                                          \
77
  { x, QueryPlanner::Opcode(OpReg::P3, BIGINT_TYPE) }
78
79
/**
80
 * @brief A map from opcode to pair of result register and resultant type.
81
 *
82
 * For most opcodes we can deduce a column type based on an interred input
83
 * to the opcode "function". These come in a few sets, arithmetic operators,
84
 * comparators, aggregates, and copies.
85
 */
86
const std::map<std::string, QueryPlanner::Opcode> kSQLOpcodes = {
87
    {"Concat", QueryPlanner::Opcode(OpReg::P3, TEXT_TYPE)},
88
    {"AggStep", QueryPlanner::Opcode(OpReg::P3, BIGINT_TYPE)},
89
    {"AggStep0", QueryPlanner::Opcode(OpReg::P3, BIGINT_TYPE)},
90
    {"Integer", QueryPlanner::Opcode(OpReg::P2, INTEGER_TYPE)},
91
    {"Int64", QueryPlanner::Opcode(OpReg::P2, BIGINT_TYPE)},
92
    {"String", QueryPlanner::Opcode(OpReg::P2, TEXT_TYPE)},
93
    {"String8", QueryPlanner::Opcode(OpReg::P2, TEXT_TYPE)},
94
    {"Or", QueryPlanner::Opcode(OpReg::P3, INTEGER_TYPE)},
95
    {"And", QueryPlanner::Opcode(OpReg::P3, INTEGER_TYPE)},
96
97
    // Arithmetic yields a BIGINT for safety.
98
    Arithmetic("BitAnd"),
99
    Arithmetic("BitOr"),
100
    Arithmetic("ShiftLeft"),
101
    Arithmetic("ShiftRight"),
102
    Arithmetic("Add"),
103
    Arithmetic("Subtract"),
104
    Arithmetic("Multiply"),
105
    Arithmetic("Divide"),
106
    Arithmetic("Remainder"),
107
108
    // Comparators result in booleans and are treated as INTEGERs.
109
    OpComparator("Not"),
110
    OpComparator("IsNull"),
111
    OpComparator("NotNull"),
112
    OpComparator("Ne"),
113
    OpComparator("Eq"),
114
    OpComparator("Gt"),
115
    OpComparator("Le"),
116
    OpComparator("Lt"),
117
    OpComparator("Ge"),
118
    OpComparator("IfNeg"),
119
    OpComparator("IfNotZero"),
120
};
121
122
RecursiveMutex SQLiteDBInstance::kPrimaryAttachMutex;
123
124
/// The SQLiteSQLPlugin implements the "sql" registry for internal/core.
125
class SQLiteSQLPlugin : public SQLPlugin {
126
 public:
127
  /// Execute SQL and store results.
128
  Status query(const std::string& query,
129
               QueryData& results,
130
               bool use_cache) const override;
131
132
  /// Introspect, explain, the suspected types selected in an SQL statement.
133
  Status getQueryColumns(const std::string& query,
134
                         TableColumns& columns) const override;
135
136
  /// Similar to getQueryColumns but return the scanned tables.
137
  Status getQueryTables(const std::string& query,
138
                        std::vector<std::string>& tables) const override;
139
140
  /// Create a SQLite module and attach (CREATE).
141
  Status attach(const std::string& name) override;
142
143
  /// Detach a virtual table (DROP).
144
  Status detach(const std::string& name) override;
145
};
146
147
/// SQL provider for osquery internal/core.
148
REGISTER_INTERNAL(SQLiteSQLPlugin, "sql", "sql");
149
150
1.33k
std::string getStringForSQLiteReturnCode(int code) {
151
1.33k
  if (kSQLiteReturnCodes.find(code) != kSQLiteReturnCodes.end()) {
152
1.33k
    return kSQLiteReturnCodes.at(code);
153
1.33k
  } else {
154
0
    std::ostringstream s;
155
0
    s << "Error: " << code << " is not a valid SQLite result code";
156
0
    return s.str();
157
0
  }
158
1.33k
}
159
160
Status SQLiteSQLPlugin::query(const std::string& query,
161
                              QueryData& results,
162
8.39k
                              bool use_cache) const {
163
8.39k
  auto dbc = SQLiteDBManager::get();
164
8.39k
  dbc->useCache(use_cache);
165
8.39k
  auto result = queryInternal(query, results, dbc);
166
8.39k
  dbc->clearAffectedTables();
167
8.39k
  return result;
168
8.39k
}
169
170
Status SQLiteSQLPlugin::getQueryColumns(const std::string& query,
171
0
                                        TableColumns& columns) const {
172
0
  auto dbc = SQLiteDBManager::get();
173
0
  return getQueryColumnsInternal(query, columns, dbc);
174
0
}
175
176
Status SQLiteSQLPlugin::getQueryTables(const std::string& query,
177
0
                                       std::vector<std::string>& tables) const {
178
0
  auto dbc = SQLiteDBManager::get();
179
0
  QueryPlanner planner(query, dbc);
180
0
  tables = planner.tables();
181
0
  return Status(0);
182
0
}
183
184
0
SQLInternal::SQLInternal(const std::string& query, bool use_cache) {
185
0
  auto dbc = SQLiteDBManager::get();
186
0
  dbc->useCache(use_cache);
187
0
  status_ = queryInternal(query, resultsTyped_, dbc);
188
189
  // One of the advantages of using SQLInternal (aside from the Registry-bypass)
190
  // is the ability to "deep-inspect" the table attributes and actions.
191
0
  event_based_ = (dbc->getAttributes() & TableAttributes::EVENT_BASED) != 0;
192
193
0
  dbc->clearAffectedTables();
194
0
}
195
196
0
QueryDataTyped& SQLInternal::rowsTyped() {
197
0
  return resultsTyped_;
198
0
}
199
200
0
const Status& SQLInternal::getStatus() const {
201
0
  return status_;
202
0
}
203
204
0
bool SQLInternal::eventBased() const {
205
0
  return event_based_;
206
0
}
207
208
// Temporary:  I'm going to move this from sql.cpp to here in change immediately
209
// following since this is the only place we actually use it (breaking up to
210
// make CRs smaller)
211
extern void escapeNonPrintableBytesEx(std::string& str);
212
213
class StringEscaperVisitor : public boost::static_visitor<> {
214
 public:
215
0
  void operator()(long long& i) const { // NO-OP
216
0
  }
217
218
0
  void operator()(double& d) const { // NO-OP
219
0
  }
220
221
0
  void operator()(std::string& str) const {
222
0
    escapeNonPrintableBytesEx(str);
223
0
  }
224
};
225
226
class SizeVisitor : public boost::static_visitor<> {
227
 public:
228
0
  void operator()(const long long& i) {
229
0
    size = sizeof(i);
230
0
  }
231
232
0
  void operator()(const double& d) {
233
0
    size = sizeof(d);
234
0
  }
235
236
0
  void operator()(const std::string& t) {
237
0
    size = t.length();
238
0
  }
239
240
0
  uint64_t get_size() const {
241
0
    return size;
242
0
  }
243
244
 private:
245
  uint64_t size{0};
246
};
247
248
0
void SQLInternal::escapeResults() {
249
0
  StringEscaperVisitor visitor;
250
0
  for (auto& rowTyped : resultsTyped_) {
251
0
    for (auto& column : rowTyped) {
252
0
      boost::apply_visitor(visitor, column.second);
253
0
    }
254
0
  }
255
0
}
256
257
0
uint64_t SQLInternal::getSize() {
258
0
  SizeVisitor visitor;
259
0
  uint64_t size = 0;
260
0
  for (const auto& row : rowsTyped()) {
261
0
    for (const auto& column : row) {
262
0
      size += column.first.size();
263
0
      boost::apply_visitor(visitor, column.second);
264
0
      size += visitor.get_size();
265
0
    }
266
0
  }
267
0
  return size;
268
0
}
269
270
612
Status SQLiteSQLPlugin::attach(const std::string& name) {
271
612
  PluginResponse response;
272
612
  auto status =
273
612
      Registry::call("table", name, {{"action", "columns"}}, response);
274
612
  if (!status.ok()) {
275
0
    return status;
276
0
  }
277
278
612
  bool is_extension = true;
279
280
  // Attach requests occurring via the plugin/registry APIs must act on the
281
  // primary database. To allow this, getConnection can explicitly request the
282
  // primary instance and avoid the contention decisions.
283
612
  auto dbc = SQLiteDBManager::getConnection(true);
284
285
  // Attach as an extension, allowing read/write tables
286
612
  return attachTableInternal(name, dbc, is_extension);
287
612
}
288
289
0
Status SQLiteSQLPlugin::detach(const std::string& name) {
290
  // Detach requests occurring via the plugin/registry APIs must act on the
291
  // primary database. To allow this, getConnection can explicitly request the
292
  // primary instance and avoid the contention decisions.
293
0
  auto dbc = SQLiteDBManager::getConnection(true);
294
0
  return detachTableInternal(name, dbc);
295
0
}
296
297
SQLiteDBInstance::SQLiteDBInstance(sqlite3*& db, Mutex& mtx)
298
8.40k
    : db_(db), lock_(mtx, boost::try_to_lock) {
299
8.40k
  if (lock_.owns_lock()) {
300
8.40k
    primary_ = true;
301
8.40k
  } else {
302
0
    db_ = nullptr;
303
0
    VLOG(1) << "DBManager contention: opening transient SQLite database";
304
0
    init();
305
0
  }
306
8.40k
}
307
308
// This function is called by SQLite when a statement is prepared and we use
309
// it to allowlist specific actions.
310
int sqliteAuthorizer(void* userData,
311
                     int code,
312
                     const char* arg3,
313
                     const char* arg4,
314
                     const char* arg5,
315
311k
                     const char* arg6) {
316
311k
  if (kAllowedSQLiteActionCodes.count(code) > 0) {
317
311k
    return SQLITE_OK;
318
311k
  }
319
320
  // For PRAGMA check the name of the PRAGMA being called.
321
238
  if (code == SQLITE_PRAGMA && arg3 != nullptr) {
322
53
    std::string pragma = arg3;
323
53
    std::transform(pragma.begin(), pragma.end(), pragma.begin(), ::tolower);
324
53
    if (kAllowedSQLitePragmas.count(pragma) > 0) {
325
0
      return SQLITE_OK;
326
0
    }
327
53
  }
328
329
238
  LOG(ERROR) << "Authorizer denied action " << code << " "
330
238
             << (arg3 ? arg3 : "null") << " " << (arg4 ? arg4 : "null") << " "
331
238
             << (arg5 ? arg5 : "null") << " " << (arg6 ? arg6 : "null");
332
238
  return SQLITE_DENY;
333
238
}
334
335
4
static inline void openOptimized(sqlite3*& db) {
336
4
  sqlite3_open(":memory:", &db);
337
338
4
  std::string settings;
339
28
  for (const auto& setting : kMemoryDBSettings) {
340
28
    settings += "PRAGMA " + setting.first + "=" + setting.second + "; ";
341
28
  }
342
4
  sqlite3_exec(db, settings.c_str(), nullptr, nullptr, nullptr);
343
344
  // Register versioning collations and function.
345
4
  registerVersionExtensions(db);
346
347
  // Register function extensions.
348
4
  registerMathExtensions(db);
349
4
#if !defined(FREEBSD)
350
4
  registerStringExtensions(db);
351
4
#endif
352
4
#if !defined(SKIP_CARVER)
353
4
  registerOperationExtensions(db);
354
4
#endif
355
4
  registerFilesystemExtensions(db);
356
4
  registerHashingExtensions(db);
357
4
  registerEncodingExtensions(db);
358
4
  registerNetworkExtensions(db);
359
360
4
  auto rc = sqlite3_set_authorizer(db, &sqliteAuthorizer, nullptr);
361
4
  if (rc != SQLITE_OK) {
362
0
    LOG(ERROR) << "Failed to set sqlite authorizer: " << sqlite3_errmsg(db);
363
0
    requestShutdown(rc);
364
0
  }
365
4
}
366
367
0
void SQLiteDBInstance::init() {
368
0
  primary_ = false;
369
0
  openOptimized(db_);
370
0
}
371
372
8.39k
void SQLiteDBInstance::useCache(bool use_cache) {
373
8.39k
  use_cache_ = use_cache;
374
8.39k
}
375
376
1.02M
bool SQLiteDBInstance::useCache() const {
377
1.02M
  return use_cache_;
378
1.02M
}
379
380
27.8k
RecursiveLock SQLiteDBInstance::attachLock() const {
381
27.8k
  if (isPrimary()) {
382
27.8k
    return RecursiveLock(kPrimaryAttachMutex);
383
27.8k
  }
384
0
  return RecursiveLock(attach_mutex_);
385
27.8k
}
386
387
void SQLiteDBInstance::addAffectedTable(
388
1.07M
    std::shared_ptr<VirtualTableContent> table) {
389
  // An xFilter/scan was requested for this virtual table.
390
1.07M
  affected_tables_.insert(std::make_pair(table->name, std::move(table)));
391
1.07M
}
392
393
0
bool SQLiteDBInstance::tableCalled(VirtualTableContent const& table) {
394
0
  return (affected_tables_.count(table.name) > 0);
395
0
}
396
397
0
TableAttributes SQLiteDBInstance::getAttributes() const {
398
0
  const SQLiteDBInstance* rdbc = this;
399
0
  if (isPrimary() && !managed_) {
400
    // Similarly to clearAffectedTables, the connection may be forwarded.
401
0
    rdbc = SQLiteDBManager::getConnection(true).get();
402
0
  }
403
404
0
  TableAttributes attributes = TableAttributes::NONE;
405
0
  for (const auto& table : rdbc->affected_tables_) {
406
0
    attributes = table.second->attributes | attributes;
407
0
  }
408
0
  return attributes;
409
0
}
410
411
16.7k
void SQLiteDBInstance::clearAffectedTables() {
412
16.7k
  if (isPrimary() && !managed_) {
413
    // A primary instance must forward clear requests to the DB manager's
414
    // 'connection' instance. This is a temporary primary instance.
415
8.39k
    SQLiteDBManager::getConnection(true)->clearAffectedTables();
416
8.39k
    return;
417
8.39k
  }
418
419
8.39k
  for (const auto& table : affected_tables_) {
420
2.69k
    table.second->constraints.clear();
421
2.69k
    table.second->cache.clear();
422
2.69k
    table.second->colsUsed.clear();
423
2.69k
    table.second->colsUsedBitsets.clear();
424
2.69k
  }
425
  // Since the affected tables are cleared, there are no more affected tables.
426
  // There is no concept of compounding tables between queries.
427
8.39k
  affected_tables_.clear();
428
8.39k
  use_cache_ = false;
429
8.39k
}
430
431
8.40k
SQLiteDBInstance::~SQLiteDBInstance() {
432
8.40k
  if (!isPrimary() && db_ != nullptr) {
433
0
    sqlite3_close(db_);
434
8.40k
  } else {
435
8.40k
    db_ = nullptr;
436
8.40k
  }
437
8.40k
}
438
439
4
SQLiteDBManager::SQLiteDBManager() : db_(nullptr) {
440
4
  sqlite3_soft_heap_limit64(1);
441
4
  setDisabledTables(Flag::getValue("disable_tables"));
442
4
  setEnabledTables(Flag::getValue("enable_tables"));
443
4
}
444
445
1.21k
bool SQLiteDBManager::isDisabled(const std::string& table_name) {
446
1.21k
  bool disabled_set = !Flag::isDefault("disable_tables");
447
1.21k
  bool enabled_set = !Flag::isDefault("enable_tables");
448
1.21k
  if (!disabled_set && !enabled_set) {
449
    // We have zero enabled tables and zero disabled tables.
450
    // As a result, no tables are disabled.
451
0
    return false;
452
0
  }
453
1.21k
  const auto& element_disabled = instance().disabled_tables_.find(table_name);
454
1.21k
  const auto& element_enabled = instance().enabled_tables_.find(table_name);
455
1.21k
  bool table_disabled = (element_disabled != instance().disabled_tables_.end());
456
1.21k
  bool table_enabled = (element_enabled != instance().enabled_tables_.end());
457
458
1.21k
  if (table_disabled) {
459
12
    return true;
460
12
  }
461
462
1.20k
  if (table_enabled && disabled_set && !table_disabled) {
463
0
    return false;
464
0
  }
465
466
1.20k
  if (table_enabled && !disabled_set) {
467
0
    return false;
468
0
  }
469
470
1.20k
  if (enabled_set && !table_enabled) {
471
0
    return true;
472
0
  }
473
474
1.20k
  if (disabled_set && !table_disabled) {
475
1.20k
    return false;
476
1.20k
  }
477
478
0
  return true;
479
1.20k
}
480
481
0
void SQLiteDBManager::resetPrimary() {
482
0
  auto& self = instance();
483
484
0
  WriteLock connection_lock(self.mutex_);
485
0
  self.connection_.reset();
486
487
0
  {
488
0
    WriteLock create_lock(self.create_mutex_);
489
0
    sqlite3_close(self.db_);
490
0
    self.db_ = nullptr;
491
0
  }
492
0
}
493
494
4
void SQLiteDBManager::setDisabledTables(const std::string& list) {
495
4
  const auto& tables = split(list, ",");
496
4
  disabled_tables_ =
497
4
      std::unordered_set<std::string>(tables.begin(), tables.end());
498
4
}
499
500
4
void SQLiteDBManager::setEnabledTables(const std::string& list) {
501
4
  const auto& tables = split(list, ",");
502
4
  enabled_tables_ =
503
4
      std::unordered_set<std::string>(tables.begin(), tables.end());
504
4
}
505
506
0
SQLiteDBInstanceRef SQLiteDBManager::getUnique() {
507
0
  auto instance = std::make_shared<SQLiteDBInstance>();
508
0
  attachVirtualTables(instance);
509
0
  return instance;
510
0
}
511
512
17.4k
SQLiteDBInstanceRef SQLiteDBManager::getConnection(bool primary) {
513
17.4k
  auto& self = instance();
514
17.4k
  WriteLock lock(self.create_mutex_);
515
516
17.4k
  if (self.db_ == nullptr) {
517
    // Create primary SQLite DB instance.
518
4
    openOptimized(self.db_);
519
4
    self.connection_ = SQLiteDBInstanceRef(new SQLiteDBInstance(self.db_));
520
4
    attachVirtualTables(self.connection_);
521
4
  }
522
523
  // Internal usage may request the primary connection explicitly.
524
17.4k
  if (primary) {
525
9.00k
    return self.connection_;
526
9.00k
  }
527
528
  // Create a 'database connection' for the managed database instance.
529
8.40k
  auto instance = std::make_shared<SQLiteDBInstance>(self.db_, self.mutex_);
530
8.40k
  if (!instance->isPrimary()) {
531
0
    attachVirtualTables(instance);
532
0
  }
533
534
8.40k
  return instance;
535
17.4k
}
536
537
4
SQLiteDBManager::~SQLiteDBManager() {
538
4
  connection_ = nullptr;
539
4
  if (db_ != nullptr) {
540
4
    sqlite3_close(db_);
541
4
    db_ = nullptr;
542
4
  }
543
4
}
544
545
QueryPlanner::QueryPlanner(const std::string& query,
546
0
                           const SQLiteDBInstanceRef& instance) {
547
0
  QueryData plan;
548
0
  queryInternal("EXPLAIN QUERY PLAN " + query, plan, instance);
549
0
  queryInternal("EXPLAIN " + query, program_, instance);
550
551
0
  for (const auto& row : plan) {
552
0
    auto details = osquery::split(row.at("detail"));
553
0
    if (details.size() > 1 && details[0] == "SCAN") {
554
0
      tables_.push_back(details[1]);
555
0
    }
556
0
  }
557
558
0
  instance->clearAffectedTables();
559
0
}
560
561
0
Status QueryPlanner::applyTypes(TableColumns& columns) {
562
0
  std::map<size_t, ColumnType> column_types;
563
0
  for (const auto& row : program_) {
564
0
    if (row.at("opcode") == "ResultRow") {
565
      // The column parsing is finished.
566
0
      auto k = boost::lexical_cast<size_t>(row.at("p1"));
567
0
      for (const auto& type : column_types) {
568
0
        if (type.first - k < columns.size()) {
569
0
          std::get<1>(columns[type.first - k]) = type.second;
570
0
        }
571
0
      }
572
0
    }
573
574
0
    if (row.at("opcode") == "Copy") {
575
      // Copy P1 -> P1 + P3 into P2 -> P2 + P3.
576
0
      auto from = boost::lexical_cast<size_t>(row.at("p1"));
577
0
      auto to = boost::lexical_cast<size_t>(row.at("p2"));
578
0
      auto size = boost::lexical_cast<size_t>(row.at("p3"));
579
0
      for (size_t i = 0; i <= size; i++) {
580
0
        if (column_types.count(from + i)) {
581
0
          column_types[to + i] = std::move(column_types[from + i]);
582
0
          column_types.erase(from + i);
583
0
        }
584
0
      }
585
0
    } else if (row.at("opcode") == "Cast") {
586
0
      auto value = boost::lexical_cast<size_t>(row.at("p1"));
587
0
      auto to = boost::lexical_cast<size_t>(row.at("p2"));
588
0
      switch (to) {
589
0
      case 'A': // BLOB
590
0
        column_types[value] = BLOB_TYPE;
591
0
        break;
592
0
      case 'B': // TEXT
593
0
        column_types[value] = TEXT_TYPE;
594
0
        break;
595
0
      case 'C': // NUMERIC
596
        // We don't exactly have an equivalent to NUMERIC (which includes such
597
        // things as DATETIME and DECIMAL
598
0
        column_types[value] = UNKNOWN_TYPE;
599
0
        break;
600
0
      case 'D': // INTEGER
601
0
        column_types[value] = BIGINT_TYPE;
602
0
        break;
603
0
      case 'E': // REAL
604
0
        column_types[value] = DOUBLE_TYPE;
605
0
        break;
606
0
      default:
607
0
        column_types[value] = UNKNOWN_TYPE;
608
0
        break;
609
0
      }
610
0
    }
611
612
0
    if (kSQLOpcodes.count(row.at("opcode"))) {
613
0
      const auto& op = kSQLOpcodes.at(row.at("opcode"));
614
0
      auto k = boost::lexical_cast<size_t>(row.at(Opcode::regString(op.reg)));
615
0
      column_types[k] = op.type;
616
0
    }
617
0
  }
618
619
0
  return Status(0);
620
0
}
621
622
// Wrapper for legacy method until all uses can be replaced
623
Status queryInternal(const std::string& query,
624
                     QueryData& results,
625
8.39k
                     const SQLiteDBInstanceRef& instance) {
626
8.39k
  QueryDataTyped typedResults;
627
8.39k
  Status status = queryInternal(query, typedResults, instance);
628
8.39k
  if (status.ok()) {
629
4.55k
    results.reserve(typedResults.size());
630
31.0M
    for (const auto& row : typedResults) {
631
31.0M
      Row r;
632
36.2M
      for (const auto& col : row) {
633
36.2M
        r[col.first] = castVariant(col.second);
634
36.2M
      }
635
31.0M
      results.push_back(std::move(r));
636
31.0M
    }
637
4.55k
  }
638
8.39k
  return status;
639
8.39k
}
640
641
Status readRows(sqlite3_stmt* prepared_statement,
642
                QueryDataTyped& results,
643
23.6k
                const SQLiteDBInstanceRef& instance) {
644
  // Do nothing with a null prepared_statement (eg, if the sql was just
645
  // whitespace)
646
23.6k
  if (prepared_statement == nullptr) {
647
32
    return Status::success();
648
32
  }
649
23.5k
  int rc = sqlite3_step(prepared_statement);
650
  /* if we have a result set row... */
651
23.5k
  if (SQLITE_ROW == rc) {
652
    // First collect the column names
653
18.5k
    int num_columns = sqlite3_column_count(prepared_statement);
654
18.5k
    std::vector<std::string> colNames;
655
18.5k
    colNames.reserve(num_columns);
656
121k
    for (int i = 0; i < num_columns; i++) {
657
103k
      colNames.push_back(sqlite3_column_name(prepared_statement, i));
658
103k
    }
659
660
31.8M
    do {
661
31.8M
      RowTyped row;
662
74.6M
      for (int i = 0; i < num_columns; i++) {
663
42.8M
        switch (sqlite3_column_type(prepared_statement, i)) {
664
12.0M
        case SQLITE_INTEGER:
665
12.0M
          row[colNames[i]] = static_cast<long long>(
666
12.0M
              sqlite3_column_int64(prepared_statement, i));
667
12.0M
          break;
668
104k
        case SQLITE_FLOAT:
669
104k
          row[colNames[i]] = sqlite3_column_double(prepared_statement, i);
670
104k
          break;
671
25.6M
        case SQLITE_NULL:
672
25.6M
          row[colNames[i]] = FLAGS_nullvalue;
673
25.6M
          break;
674
5.06M
        default:
675
          // Everything else (SQLITE_TEXT, SQLITE3_TEXT, SQLITE_BLOB) is
676
          // obtained/conveyed as text/string
677
5.06M
          row[colNames[i]] = std::string(reinterpret_cast<const char*>(
678
5.06M
              sqlite3_column_text(prepared_statement, i)));
679
42.8M
        }
680
42.8M
      }
681
31.8M
      results.push_back(std::move(row));
682
31.8M
      rc = sqlite3_step(prepared_statement);
683
31.8M
    } while (SQLITE_ROW == rc);
684
18.5k
  }
685
23.5k
  if (rc != SQLITE_DONE) {
686
812
    auto s = Status::failure(sqlite3_errmsg(instance->db()));
687
812
    sqlite3_finalize(prepared_statement);
688
812
    return s;
689
812
  }
690
691
22.7k
  rc = sqlite3_finalize(prepared_statement);
692
22.7k
  if (rc != SQLITE_OK) {
693
0
    return Status::failure(sqlite3_errmsg(instance->db()));
694
0
  }
695
696
22.7k
  return Status::success();
697
22.7k
}
698
699
Status queryInternal(const std::string& query,
700
                     QueryDataTyped& results,
701
8.39k
                     const SQLiteDBInstanceRef& instance) {
702
8.39k
  sqlite3_stmt* prepared_statement{nullptr}; /* Statement to execute. */
703
704
8.39k
  int rc = SQLITE_OK; /* Return Code */
705
8.39k
  const char* leftover_sql = nullptr; /* Tail of unprocessed SQL */
706
8.39k
  const char* sql = query.c_str(); /* SQL to be processed */
707
708
  /* The big while loop.  One iteration per statement */
709
31.1k
  while ((sql[0] != '\0') && (SQLITE_OK == rc)) {
710
26.6k
    const auto lock = instance->attachLock();
711
712
    // Trim leading whitespace
713
29.3k
    while (isspace(sql[0])) {
714
2.72k
      sql++;
715
2.72k
    }
716
26.6k
    rc = sqlite3_prepare_v2(
717
26.6k
        instance->db(), sql, -1, &prepared_statement, &leftover_sql);
718
26.6k
    if (rc != SQLITE_OK) {
719
3.02k
      Status s = Status::failure(sqlite3_errmsg(instance->db()));
720
3.02k
      sqlite3_finalize(prepared_statement);
721
3.02k
      return s;
722
3.02k
    }
723
724
23.6k
    Status s = readRows(prepared_statement, results, instance);
725
23.6k
    if (!s.ok()) {
726
812
      return s;
727
812
    }
728
729
22.8k
    sql = leftover_sql;
730
22.8k
  } /* end while */
731
4.55k
  sqlite3_db_release_memory(instance->db());
732
4.55k
  return Status::success();
733
8.39k
}
734
735
Status getQueryColumnsInternal(const std::string& q,
736
                               TableColumns& columns,
737
0
                               const SQLiteDBInstanceRef& instance) {
738
0
  Status status = Status();
739
0
  TableColumns results;
740
0
  {
741
0
    auto lock = instance->attachLock();
742
743
    // Turn the query into a prepared statement
744
0
    sqlite3_stmt* stmt{nullptr};
745
0
    auto rc = sqlite3_prepare_v2(instance->db(),
746
0
                                 q.c_str(),
747
0
                                 static_cast<int>(q.length() + 1),
748
0
                                 &stmt,
749
0
                                 nullptr);
750
0
    if (rc != SQLITE_OK || stmt == nullptr) {
751
0
      auto s = Status::failure(sqlite3_errmsg(instance->db()));
752
0
      if (stmt != nullptr) {
753
0
        sqlite3_finalize(stmt);
754
0
      }
755
0
      return s;
756
0
    }
757
758
    // Get column count
759
0
    auto num_columns = sqlite3_column_count(stmt);
760
0
    results.reserve(num_columns);
761
762
    // Get column names and types
763
0
    bool unknown_type = false;
764
0
    for (int i = 0; i < num_columns; ++i) {
765
0
      auto col_name = sqlite3_column_name(stmt, i);
766
0
      auto col_type = sqlite3_column_decltype(stmt, i);
767
768
0
      if (col_name == nullptr) {
769
0
        status = Status(1, "Could not get column type");
770
0
        break;
771
0
      }
772
773
0
      if (col_type == nullptr) {
774
        // Types are only returned for table columns (not expressions).
775
0
        col_type = "UNKNOWN";
776
0
        unknown_type = true;
777
0
      }
778
0
      results.push_back(std::make_tuple(
779
0
          col_name, columnTypeName(col_type), ColumnOptions::DEFAULT));
780
0
    }
781
782
    // An unknown type means we have to parse the plan and SQLite opcodes.
783
0
    if (unknown_type) {
784
0
      QueryPlanner planner(q, instance);
785
0
      planner.applyTypes(results);
786
0
    }
787
0
    sqlite3_finalize(stmt);
788
0
  }
789
790
0
  if (status.ok()) {
791
0
    columns = std::move(results);
792
0
  }
793
794
0
  return status;
795
0
}
796
} // namespace osquery