void PreparedStatement::init(thread_db* tdbb, Attachment* attachment, jrd_tra* transaction, const Firebird::string& text, bool isInternalRequest) { AutoSetRestore<SSHORT> autoAttCharset(&attachment->att_charset, (isInternalRequest ? CS_METADATA : attachment->att_charset)); request = NULL; try { const Database& dbb = *tdbb->getDatabase(); const int dialect = isInternalRequest || (dbb.dbb_flags & DBB_DB_SQL_dialect_3) ? SQL_DIALECT_V6 : SQL_DIALECT_V5; request = DSQL_prepare(tdbb, attachment, transaction, text.length(), text.c_str(), dialect, NULL, NULL, isInternalRequest); const DsqlCompiledStatement* statement = request->getStatement(); if (statement->getSendMsg()) parseDsqlMessage(statement->getSendMsg(), inValues, inMetadata, inMessage); if (statement->getReceiveMsg()) parseDsqlMessage(statement->getReceiveMsg(), outValues, outMetadata, outMessage); } catch (const Exception&) { if (request) { DSQL_free_statement(tdbb, request, DSQL_drop); } throw; } }
Firebird::string pagtype(UCHAR type) { // Print pretty name for database page type const char* nameArray[pag_max + 1] = { "purposely undefined", "database header", "page inventory", "transaction inventory", "pointer", "data", "index root", "index B-tree", "blob", "generators", "SCN inventory" }; Firebird::string rc; if (type < FB_NELEM(nameArray)) rc = nameArray[type]; else rc.printf("unknown (%d)", type); return rc; }
bool readenv(const char* env_name, Firebird::PathName& env_value) { Firebird::string result; bool rc = readenv(env_name, result); env_value.assign(result.c_str(), result.length()); return rc; }
// create directory for lock files and set appropriate access rights void createLockDirectory(const char* pathname) { static bool errorLogged = false; DWORD attr = GetFileAttributes(pathname); DWORD errcode = 0; if (attr == INVALID_FILE_ATTRIBUTES) { errcode = GetLastError(); if (errcode == ERROR_FILE_NOT_FOUND) { if (!CreateDirectory(pathname, NULL)) { errcode = GetLastError(); } else { adjustLockDirectoryAccess(pathname); attr = GetFileAttributes(pathname); if (attr == INVALID_FILE_ATTRIBUTES) { errcode = GetLastError(); } } } } Firebird::string err; if (attr == INVALID_FILE_ATTRIBUTES) { err.printf("Can't create directory \"%s\". OS errno is %d", pathname, errcode); if (!errorLogged) { errorLogged = true; gds__log(err.c_str()); } Firebird::fatal_exception::raise(err.c_str()); } if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { err.printf("Can't create directory \"%s\". File with same name already exists", pathname); if (!errorLogged) { errorLogged = true; gds__log(err.c_str()); } Firebird::fatal_exception::raise(err.c_str()); } if (attr & FILE_ATTRIBUTE_READONLY) { err.printf("Can't create directory \"%s\". Readonly directory with same name already exists", pathname); if (!errorLogged) { errorLogged = true; gds__log(err.c_str()); } Firebird::fatal_exception::raise(err.c_str()); } }
ModuleLoader::Module* ModuleLoader::loadModule(ISC_STATUS* status, const Firebird::PathName& modPath) { void* module = dlopen(modPath.nullStr(), FB_RTLD_MODE); if (module == NULL) { if (status) { status[0] = isc_arg_gds; status[1] = isc_random; status[2] = isc_arg_string; status[3] = (ISC_STATUS) dlerror(); status[4] = isc_arg_end; } return 0; } #ifdef DEBUG_THREAD_IN_UNLOADED_LIBRARY Firebird::string command; command.printf("echo +++ %s +++ >>/tmp/fbmaps;date >> /tmp/fbmaps;cat /proc/%d/maps >>/tmp/fbmaps", modPath.c_str(), getpid()); system(command.c_str()); #endif return FB_NEW_POOL(*getDefaultMemoryPool()) DlfcnModule(*getDefaultMemoryPool(), modPath, module); }
TracePlugin* FB_CARG TraceFactoryImpl::trace_create(Firebird::IStatus* status, TraceInitInfo* initInfo) { Firebird::MasterInterfacePtr master; const char* dbname = NULL; try { master->upgradeInterface(initInfo, FB_TRACE_INIT_INFO_VERSION, upInfo); dbname = initInfo->getDatabaseName(); if (!dbname) dbname = ""; TracePluginConfig config; TraceCfgReader::readTraceConfiguration(initInfo->getConfigText(), dbname, config); TraceDatabaseConnection* connection = initInfo->getConnection(); if (connection) master->upgradeInterface(connection, FB_TRACE_CONNECTION_VERSION, upInfo); if (!config.enabled || (config.connection_id && connection && (connection->getConnectionID() != SLONG(config.connection_id)))) { return NULL; // Plugin is not needed, no error happened. } Firebird::AutoPtr<TraceLogWriter, Firebird::SimpleRelease<TraceLogWriter> > logWriter(initInfo->getLogWriter()); if (logWriter) config.log_filename = ""; return new TracePluginImpl(config, initInfo); // Everything is ok, we created a plugin } catch (Firebird::Exception& ex) { // put error into trace log TraceLogWriter* logWriter = initInfo->getLogWriter(); if (logWriter) { master->upgradeInterface(logWriter, FB_TRACE_LOG_WRITER_VERSION, upInfo); const char* strEx = TracePluginImpl::marshal_exception(ex); Firebird::string err; if (dbname) err.printf("Error creating trace session for database \"%s\":\n%s\n", dbname, strEx); else err.printf("Error creating trace session for service manager attachment:\n%s\n", strEx); logWriter->write(err.c_str(), err.length()); logWriter->release(); } else ex.stuffException(status); } return NULL; }
void prepareName(Firebird::string& s, char c) { for (unsigned i = 0; i < s.length(); ++i) { if (s[i] == c) { s.insert(i++, 1, c); } } }
void Stream::format(const char *pattern, ...) { Firebird::string temp; va_list args; va_start (args, pattern); temp.vprintf(pattern, args); va_end(args); putSegment (temp.c_str()); }
void ExecuteStatement::open(thread_db* tdbb, jrd_nod* sql, SSHORT nVars, bool singleton) { SET_TDBB(tdbb); Attachment* const attachment = tdbb->getAttachment(); jrd_tra* transaction = tdbb->getTransaction(); if (transaction->tra_callback_count >= MAX_CALLBACKS) { ERR_post(Arg::Gds(isc_exec_sql_max_call_exceeded)); } varCount = nVars; singleMode = singleton; Firebird::string sqlText; getString(tdbb, sqlText, EVL_expr(tdbb, sql), tdbb->getRequest()); memcpy(startOfSqlOperator, sqlText.c_str(), sizeof(startOfSqlOperator) - 1); startOfSqlOperator[sizeof(startOfSqlOperator) - 1] = 0; transaction->tra_callback_count++; try { stmt = attachment->prepareStatement(tdbb, *tdbb->getDefaultPool(), transaction, sqlText); if (stmt->getResultCount() == 0) { delete stmt; stmt = NULL; ERR_post(Arg::Gds(isc_exec_sql_invalid_req) << Arg::Str(startOfSqlOperator)); } if (stmt->getResultCount() != varCount) { delete stmt; stmt = NULL; ERR_post(Arg::Gds(isc_wronumarg)); } resultSet = stmt->executeQuery(tdbb, transaction); fb_assert(transaction == tdbb->getTransaction()); } catch (const Firebird::Exception&) { transaction->tra_callback_count--; throw; } transaction->tra_callback_count--; }
void* DlfcnModule::findSymbol(const Firebird::string& symName) { void* result = dlsym(module, symName.c_str()); if (result == NULL) { Firebird::string newSym ='_' + symName; result = dlsym(module, newSym.c_str()); } return result; }
void iscDbLogStatus(const TEXT* text, Firebird::IStatus* status) { const TEXT* hdr = NULL; Firebird::string buf; if (text) { buf = "Database: "; buf += text; hdr = buf.c_str(); } iscLogStatus(hdr, status); }
Firebird::string Stream::getFBString() const { Firebird::string string; char *p = string.getBuffer (totalLength); for (const Segment *segment = segments; segment; segment = segment->next) { memcpy (p, segment->address, segment->length); p += segment->length; } fb_assert(p - string.begin() == totalLength); return string; }
// converts bytes to BASE64 representation void base64(Firebird::string& b64, const Firebird::UCharBuffer& bin) { b64.erase(); const unsigned char* f = bin.begin(); for (int i = bin.getCount(); i > 0; i -= 3, f += 3) { if (i >= 3) { const ULONG l = (ULONG(f[0]) << 16) | (ULONG(f[1]) << 8) | f[2]; b64 += conv_bin2ascii(l >> 18); b64 += conv_bin2ascii(l >> 12); b64 += conv_bin2ascii(l >> 6); b64 += conv_bin2ascii(l); } else { ULONG l = ULONG(f[0]) << 16; if (i == 2) l |= (ULONG(f[1]) << 8); b64 += conv_bin2ascii(l >> 18); b64 += conv_bin2ascii(l >> 12); b64 += (i == 1 ? '=' : conv_bin2ascii(l >> 6)); b64 += '='; } }
static void alice_output(bool error, const SCHAR* format, ...) { AliceGlobals* tdgbl = AliceGlobals::getSpecific(); va_list arglist; va_start(arglist, format); Firebird::string buf; buf.vprintf(format, arglist); va_end(arglist); if (error) tdgbl->uSvc->outputError(buf.c_str()); else tdgbl->uSvc->outputVerbose(buf.c_str()); }
static void stuff_stack_trace(const jrd_req* request) { Firebird::string sTrace; bool isEmpty = true; for (const jrd_req* req = request; req; req = req->req_caller) { const JrdStatement* statement = req->getStatement(); Firebird::string name; if (statement->triggerName.length()) { name = "At trigger '"; name += statement->triggerName.c_str(); } else if (statement->procedure) { name = statement->parentStatement ? "At sub procedure '" : "At procedure '"; name += statement->procedure->getName().toString().c_str(); } else if (statement->function) { name = statement->parentStatement ? "At sub function '" : "At function '"; name += statement->function->getName().toString().c_str(); } if (! name.isEmpty()) { name.trim(); if (sTrace.length() + name.length() + 2 > MAX_STACK_TRACE) break; if (isEmpty) { isEmpty = false; sTrace += name + "'"; } else { sTrace += "\n" + name + "'"; } if (req->req_src_line) { Firebird::string src_info; src_info.printf(" line: %"ULONGFORMAT", col: %"ULONGFORMAT, req->req_src_line, req->req_src_column); if (sTrace.length() + src_info.length() > MAX_STACK_TRACE) break; sTrace += src_info; } } } if (!isEmpty) ERR_post_nothrow(Arg::Gds(isc_stack_trace) << Arg::Str(sTrace)); }
ISC_STATUS API_ROUTINE isc_delete_user(ISC_STATUS* status, const USER_SEC_DATA* input_user_data) { /************************************** * * i s c _ d e l e t e _ u s e r * ************************************** * * Functional description * Deletes a user from the server's security * database. * Return 0 if the user was deleted * * Return > 0 if any error occurs. * **************************************/ Auth::StackUserData userInfo; userInfo.op = Auth::DEL_OPER; Firebird::LocalStatus s; Firebird::CheckStatusWrapper statusWrapper(&s); if (input_user_data->user_name) { Firebird::string work = input_user_data->user_name; if (work.length() > USERNAME_LENGTH) { return user_error(status, isc_usrname_too_long); } Firebird::string::size_type l = work.find(' '); if (l != Firebird::string::npos) { work.resize(l); } userInfo.user.set(&statusWrapper, work.c_str()); Firebird::check(&statusWrapper); userInfo.user.setEntered(&statusWrapper, 1); Firebird::check(&statusWrapper); } else { return user_error(status, isc_usrname_required); } return executeSecurityCommand(status, input_user_data, userInfo); }
// static function bool Switches::matchSwitch(const Firebird::string& sw, const char* target, size_t n) { /************************************** * * m a t c h S w i t c h * ************************************** * * Functional description * Returns true if switch matches target * **************************************/ if (n < sw.length()) { return false; } n = sw.length(); return memcmp(sw.c_str(), target, n) == 0; }
// Lookup and format message. Return as much of formatted string as fits in caller's buffer. int fb_msg_format(void* handle, USHORT facility, USHORT number, unsigned int bsize, TEXT* buffer, const MsgFormat::SafeArg& arg) { // The field MESSAGES.TEXT is 118 bytes long. int total_msg = 0; char msg[120] = ""; const int n = gds__msg_lookup(handle, facility, number, sizeof(msg), msg, NULL); if (n > 0 && unsigned(n) < sizeof(msg)) { // Shameful bridge, gds__msg_format emulation for old format messages. if (strchr(msg, '%')) { const TEXT* rep[5]; arg.dump(rep, 5); total_msg = fb_utils::snprintf(buffer, bsize, msg, rep[0], rep[1], rep[2], rep[3], rep[4]); } else total_msg = MsgPrint(buffer, bsize, msg, arg); } else { Firebird::string s; s.printf("can't format message %d:%d -- ", facility, number); if (n == -1) s += "message text not found"; else if (n == -2) { s += "message file "; s += fb_utils::getPrefix(Firebird::DirType::FB_DIR_MSG, MSG_FILE).ToString(); s += " not found"; } else { fb_utils::snprintf(buffer, bsize, "message system code %d", n); s += buffer; } total_msg = s.copyTo(buffer, bsize); } return (n > 0 ? total_msg : -total_msg); }
// fetch password from file FetchPassResult fetchPassword(const Firebird::PathName& name, const char*& password) { InputFile file(name); if (!file) { return FETCH_PASS_FILE_OPEN_ERROR; } Firebird::string pwd; if (! pwd.LoadFromFile(file.getStdioFile())) { return ferror(file.getStdioFile()) ? FETCH_PASS_FILE_READ_ERROR : FETCH_PASS_FILE_EMPTY; } // this is planned leak of a few bytes of memory in utilities char* pass = FB_NEW_POOL(*getDefaultMemoryPool()) char[pwd.length() + 1]; pwd.copyTo(pass, pwd.length() + 1); password = pass; return FETCH_PASS_OK; }
ModuleLoader::Module* ModuleLoader::loadModule(const Firebird::PathName& modPath) { void* module = dlopen(modPath.nullStr(), FB_RTLD_MODE); if (module == NULL) { #ifdef DEV_BUILD // gds__log("loadModule failed loading %s: %s", modPath.c_str(), dlerror()); #endif return 0; } #ifdef DEBUG_THREAD_IN_UNLOADED_LIBRARY Firebird::string command; command.printf("echo +++ %s +++ >>/tmp/fbmaps;date >> /tmp/fbmaps;cat /proc/%d/maps >>/tmp/fbmaps", modPath.c_str(), getpid()); system(command.c_str()); #endif return FB_NEW_POOL(*getDefaultMemoryPool()) DlfcnModule(module); }
size_t PAR_name(CompilerScratch* csb, Firebird::string& name) { /************************************** * * P A R _ n a m e * ************************************** * * Functional description * Parse a counted string of virtually unlimited size * (up to 64K, actually <= 255), returning count. * **************************************/ size_t l = csb->csb_blr_reader.getByte(); char* s = name.getBuffer(l); while (l--) *s++ = csb->csb_blr_reader.getByte(); return name.length(); }
void* DlfcnModule::findSymbol(const Firebird::string& symName) { void* result = dlsym(module, symName.c_str()); if (!result) { Firebird::string newSym = '_' + symName; result = dlsym(module, newSym.c_str()); } #ifdef HAVE_DLADDR if (!PathUtils::isRelative(fileName)) { Dl_info info; if (!dladdr(result, &info)) return NULL; if (fileName != info.dli_fname) return NULL; } #endif return result; }
void ExecuteStatement::getString(thread_db* tdbb, Firebird::string& sql, const dsc* desc, const jrd_req* request) { MoveBuffer buffer; UCHAR* ptr = NULL; const SSHORT len = (desc && !(request->req_flags & req_null)) ? MOV_make_string2(tdbb, desc, desc->getTextType(), &ptr, buffer) : 0; // !!! How call Msgs ? if (!ptr) { ERR_post(Arg::Gds(isc_exec_sql_invalid_arg)); } sql.assign((const char*) ptr, len); }
//*************** // r e a d e n v //*************** // Goes to read directly the environment variables from the operating system on Windows // and provides a stub for UNIX. bool readenv(const char* env_name, Firebird::string& env_value) { #ifdef WIN_NT const DWORD rc = GetEnvironmentVariable(env_name, NULL, 0); if (rc) { env_value.reserve(rc - 1); DWORD rc2 = GetEnvironmentVariable(env_name, env_value.begin(), rc); if (rc2 < rc && rc2 != 0) { env_value.recalculate_length(); return true; } } #else const char* p = getenv(env_name); if (p) return env_value.assign(p).length() != 0; #endif // Not found, clear the output var. env_value.begin()[0] = 0; env_value.recalculate_length(); return false; }
void exactNumericToStr(SINT64 value, int scale, Firebird::string& target, bool append) { if (value == 0) { if (append) target.append("0", 1); else target.assign("0", 1); return; } const int MAX_SCALE = 25; const int MAX_BUFFER = 50; if (scale < -MAX_SCALE || scale > MAX_SCALE) { fb_assert(false); return; // throw exception here? } const bool neg = value < 0; const bool dot = scale < 0; // Need the decimal separator or not? char buffer[MAX_BUFFER]; int iter = MAX_BUFFER; buffer[--iter] = '\0'; if (scale > 0) { while (scale-- > 0) buffer[--iter] = '0'; } bool dot_used = false; FB_UINT64 uval = neg ? FB_UINT64(-(value + 1)) + 1 : value; // avoid problems with MIN_SINT64 while (uval != 0) { buffer[--iter] = static_cast<char>(uval % 10) + '0'; uval /= 10; if (dot && !++scale) { buffer[--iter] = '.'; dot_used = true; } } if (dot) { // if scale > 0 we have N.M // if scale == 0 we have .M and we need 0.M // if scale < 0 we have pending zeroes and need 0.{0+}M if (!dot_used) { while (scale++ < 0) buffer[--iter] = '0'; buffer[--iter] = '.'; buffer[--iter] = '0'; } else if (!scale) buffer[--iter] = '0'; } if (neg) buffer[--iter] = '-'; const FB_SIZE_T len = MAX_BUFFER - iter - 1; if (append) target.append(buffer + iter, len); else target.assign(buffer + iter, len); }
int CLIB_ROUTINE main( int argc, char **argv) { /************************************** * * m a i n * ************************************** * * Functional description * If there is no command line, prompt for one, read it * and make an artificial argc/argv. Otherwise, pass * the specified argc/argv to IBMGR_exec_line (see below). * **************************************/ fprintf(stderr, "*** fbmgr is deprecated, will be removed soon ***\n"); gds__log("*** fbmgr is deprecated, will be removed soon ***"); // Let's see if we have something in environment variables Firebird::string user, password; fb_utils::readenv(ISC_USER, user); fb_utils::readenv(ISC_PASSWORD, password); Firebird::string host; // MMM - do not allow to change host now //fb_utils::readenv("ISC_HOST", host); TEXT msg[MSG_LEN]; // Let's get a real user name. This info is used by // START server command. Because server is not running // we can not check the password, thus we require a // real user to be root or FIREBIRD_USER_NAME or // INTERBASE_USER_NAME or INTERBASE_USER_SHORT const struct passwd* pw = getpwuid(getuid()); if (pw == NULL) { perror("getpwuid"); SRVRMGR_msg_get(MSG_GETPWFAIL, msg); fprintf(OUTFILE, "%s\n", msg); exit(FINI_ERROR); } strcpy(ibmgr_data.real_user, pw->pw_name); if (!strcmp(pw->pw_name, "root") || !strcmp(pw->pw_name, FIREBIRD_USER_NAME) || !strcmp(pw->pw_name, INTERBASE_USER_NAME) || !strcmp(pw->pw_name, INTERBASE_USER_SHORT)) { strcpy(ibmgr_data.user, SYSDBA_USER_NAME); } else copy_str_upper(ibmgr_data.user, pw->pw_name); if (user.length()) copy_str_upper(ibmgr_data.user, user.c_str()); if (password.length()) strcpy(ibmgr_data.password, password.c_str()); else ibmgr_data.password[0] = '\0'; if (host.length()) strcpy(ibmgr_data.host, host.c_str()); else strcpy(ibmgr_data.host, "localhost"); // Shutdown is not in progress and we are not attached to service yet. // But obviously we will need attachment. ibmgr_data.shutdown = false; ibmgr_data.attached = 0; ibmgr_data.reattach |= (REA_HOST | REA_USER | REA_PASSWORD); // No pidfile by default ibmgr_data.pidfile[0] = 0; // Special case a solitary -z switch. // Print the version and then drop into prompt mode. if (argc == 2 && *argv[1] == '-' && (argv[1][1] == 'Z' || argv[1][1] == 'z')) { parse_cmd_line(argc, argv, false); argc--; } SSHORT ret; if (argc > 1) { ret = parse_cmd_line(argc, argv, true); if (ret == FB_SUCCESS) { ret = SRVRMGR_exec_line(&ibmgr_data); if (ret) { SRVRMGR_msg_get(ret, msg); fprintf(OUTFILE, "%s\n", msg); } // We also need to check the shutdown flag here (if operation was // -shut -[noat|notr]) and, depending on what we want to do, either // wait here on some sort of a shutdown event, or go to the prompt mode SRVRMGR_cleanup(&ibmgr_data); exit(FINI_OK); } else if (ret != ACT_PROMPT) exit(FINI_OK); } int local_argc; SCHAR* local_argv[MAXARGS]; TEXT stuff[MAXSTUFF]; for (;;) { if (get_line(&local_argc, local_argv, stuff)) break; if (local_argc > 1) { ret = parse_cmd_line(local_argc, local_argv, false); if (ret == ACT_QUIT) break; if (ret == FB_SUCCESS) { ret = SRVRMGR_exec_line(&ibmgr_data); if (ret) { SRVRMGR_msg_get(ret, msg); fprintf(OUTFILE, "%s\n", msg); } } } } SRVRMGR_cleanup(&ibmgr_data); exit(FINI_OK); }
qli_tok* LEX_token() { /************************************** * * L E X _ t o k e n * ************************************** * * Functional description * Parse and return the next token. * **************************************/ qli_tok* token = QLI_token; TEXT* p = token->tok_string; // Get next significant byte. If it's the last EOL of a blob, throw it away SSHORT c; for (;;) { c = skip_white(); if (c != '\n' || QLI_line->line_type != line_blob) break; qli_line* prior = QLI_line; next_line(true); if (prior == QLI_line) break; } // If we hit end of file, make up a phoney token if (!QLI_line) { const TEXT* q = eof_string; while (*p++ = *q++); token->tok_type = tok_eof; token->tok_keyword = KW_none; return NULL; } *p++ = c; QLI_token->tok_position = QLI_line->line_position + QLI_line->line_ptr - QLI_line->line_data - 1; // On end of file, generate furious but phone end of line tokens char char_class = classes(c); if (char_class & CHR_letter) { for (c = nextchar(true); classes(c) & CHR_ident; c = nextchar(true)) *p++ = c; retchar(); token->tok_type = tok_ident; } else if (((char_class & CHR_digit) || c == '.') && scan_number(c, &p)) token->tok_type = tok_number; else if (char_class & CHR_quote) { token->tok_type = tok_quoted; while (true) { const SSHORT next = nextchar(false); if (!next || next == '\n') { retchar(); IBERROR(63); // Msg 63 unterminated quoted string break; } *p++ = next; if ((p - token->tok_string) >= MAXSYMLEN) ERRQ_msg_put(470, SafeArg() << MAXSYMLEN); // Msg 470 literal too long // If there are 2 quotes in a row, interpret 2nd as a literal if (next == c) { const SSHORT peek = nextchar(false); retchar(); if (peek != c) break; nextchar(false); } } } else if (c == '\n') { // end of line, signal it properly with a phoney token. token->tok_type = tok_eol; --p; const TEXT* q = eol_string; while (*q) *p++ = *q++; } else { token->tok_type = tok_punct; *p++ = nextchar(true); if (!HSH_lookup(token->tok_string, 2)) { retchar(); --p; } } token->tok_length = p - token->tok_string; *p = '\0'; if (token->tok_string[0] == '$' && trans_limit < TRANS_LIMIT) { Firebird::string s; if (fb_utils::readenv(token->tok_string + 1, s)) { LEX_push_string(s.c_str()); ++trans_limit; token = LEX_token(); --trans_limit; return token; } } qli_symbol* symbol = HSH_lookup(token->tok_string, token->tok_length); token->tok_symbol = symbol; if (symbol && symbol->sym_type == SYM_keyword) token->tok_keyword = (kwwords) symbol->sym_keyword; else token->tok_keyword = KW_none; if (sw_trace) puts(token->tok_string); return token; }
/** typeBuffer @brief Prints data, returned by service, using outputFunction @param status @param buf @param offset @param uData @param outputFunction @param functionArg @param text **/ static int typeBuffer(ISC_STATUS* status, char* buf, int offset, Auth::UserData& uData, Firebird::IListUsers* callback, Firebird::string& text) { const char* p = &buf[offset]; // Sanity checks if (*p++ != isc_info_svc_get_users) { status[0] = isc_arg_gds; status[1] = isc_gsec_params_not_allowed; status[2] = isc_arg_end; return -1; } FB_SIZE_T loop = static_cast<FB_SIZE_T>(isc_vax_integer (p, sizeof (USHORT))); p += sizeof (USHORT); if (p[loop] != isc_info_end) { status[0] = isc_arg_gds; status[1] = isc_gsec_params_not_allowed; status[2] = isc_arg_end; return -1; } // No data - stop processing if (! loop) { return -1; } // Old data left - use them if (offset) { memmove(&buf[offset], p, loop + 1); p = buf; loop += offset; offset = 0; } while (*p != isc_info_end) { fb_assert(p[loop] == isc_info_end); try { switch (*p++) { case isc_spb_sec_username: if (uData.user.get()[0]) { LocalStatus status; CheckStatusWrapper statusWrapper(&status); if (callback) { setAttr(&statusWrapper, &uData); check(&statusWrapper); callback->list(&statusWrapper, &uData); check(&statusWrapper); } uData.clear(&statusWrapper); check(&statusWrapper); } parseString2(p, uData.user, loop); break; case isc_spb_sec_firstname: parseString2(p, uData.first, loop); break; case isc_spb_sec_middlename: parseString2(p, uData.middle, loop); break; case isc_spb_sec_lastname: parseString2(p, uData.last, loop); break; case isc_spb_sec_groupid: parseLong(p, uData.g, loop); break; case isc_spb_sec_userid: parseLong(p, uData.u, loop); break; case isc_spb_sec_admin: parseLong(p, uData.adm, loop); break; default: // give up - treat it as gsec error text.assign(p - 1, loop + 1); return -1; } } catch (FB_SIZE_T newOffset) { memmove(buf, --p, newOffset); return newOffset; } } fb_assert(loop == 0); return 0; }
/** callRemoteServiceManager @brief Calls service manager to execute command, specified in userInfo @param status @param handle @param userInfo @param outputFunction @param functionArg **/ void callRemoteServiceManager(ISC_STATUS* status, isc_svc_handle handle, Auth::UserData& userData, Firebird::IListUsers* callback) { char spb_buffer[1024]; char* spb = spb_buffer; const int op = userData.op; if (op != Auth::DIS_OPER && op != Auth::OLD_DIS_OPER && op != Auth::MAP_SET_OPER && op != Auth::MAP_DROP_OPER && !userData.user.entered()) { status[0] = isc_arg_gds; status[1] = isc_gsec_switches_error; status[2] = isc_arg_end; return; } switch (op) { case Auth::ADD_OPER: stuffSpbByte(spb, isc_action_svc_add_user); userInfoToSpb(spb, userData); break; case Auth::MOD_OPER: stuffSpbByte(spb, isc_action_svc_modify_user); userInfoToSpb(spb, userData); break; case Auth::DEL_OPER: stuffSpbByte(spb, isc_action_svc_delete_user); stuffSpb2(spb, isc_spb_sec_username, userData.user.get()); if (userData.role.entered()) { stuffSpb2(spb, isc_spb_sql_role_name, userData.role.get()); } break; case Auth::DIS_OPER: case Auth::OLD_DIS_OPER: { char usersDisplayTag = 0; checkServerUsersVersion(handle, usersDisplayTag); stuffSpbByte(spb, usersDisplayTag); } if (userData.user.entered()) { stuffSpb2(spb, isc_spb_sec_username, userData.user.get()); } if (userData.role.entered()) { stuffSpb2(spb, isc_spb_sql_role_name, userData.role.get()); } break; case Auth::MAP_SET_OPER: stuffSpbByte(spb, isc_action_svc_set_mapping); break; case Auth::MAP_DROP_OPER: stuffSpbByte(spb, isc_action_svc_drop_mapping); break; default: status[0] = isc_arg_gds; status[1] = isc_gsec_switches_error; status[2] = isc_arg_end; return; } if (userData.database.entered()) { stuffSpb2(spb, isc_spb_dbname, userData.database.get()); } fb_assert((size_t)(spb - spb_buffer) <= sizeof(spb_buffer)); if (isc_service_start(status, &handle, 0, static_cast<USHORT>(spb - spb_buffer), spb_buffer) != 0) { return; } spb = spb_buffer; stuffSpbByte(spb, isc_info_svc_timeout); stuffSpbShort(spb, 4); stuffSpbLong(spb, 10); char resultBuffer[RESULT_BUF_SIZE + 4]; Firebird::string text; ISC_STATUS_ARRAY temp_status; ISC_STATUS* local_status = status[1] ? temp_status : status; fb_utils::init_status(local_status); if (op == Auth::DIS_OPER || op == Auth::OLD_DIS_OPER) { const char request[] = {isc_info_svc_get_users}; int startQuery = 0; Auth::StackUserData uData; for (;;) { isc_resv_handle reserved = 0; isc_service_query(local_status, &handle, &reserved, static_cast<USHORT>(spb - spb_buffer), spb_buffer, sizeof(request), request, RESULT_BUF_SIZE - startQuery, &resultBuffer[startQuery]); if (local_status[1]) { return; } startQuery = typeBuffer(local_status, resultBuffer, startQuery, uData, callback, text); if (startQuery < 0) { break; } } if (uData.user.get()[0] && callback) { LocalStatus status; CheckStatusWrapper statusWrapper(&status); setAttr(&statusWrapper, &uData); check(&statusWrapper); callback->list(&statusWrapper, &uData); check(&statusWrapper); } } else { const char request = isc_info_svc_line; for (;;) { isc_resv_handle reserved = 0; isc_service_query(local_status, &handle, &reserved, 0, NULL, 1, &request, RESULT_BUF_SIZE, resultBuffer); if (local_status[1]) { return; } char *p = resultBuffer; if (*p++ == isc_info_svc_line) { FB_SIZE_T len = static_cast<FB_SIZE_T>(isc_vax_integer(p, sizeof(USHORT))); p += sizeof(USHORT); if (len > RESULT_BUF_SIZE) { len = RESULT_BUF_SIZE; } if (!len) { if (*p == isc_info_data_not_ready) continue; if (*p == isc_info_end) break; } p[len] = 0; text += p; } } } if (! text.isEmpty()) { local_status[0] = isc_arg_interpreted; // strdup - memory leak in case of errors local_status[1] = reinterpret_cast<ISC_STATUS>(strdup(text.c_str())); local_status[2] = isc_arg_end; } }
// allow different users to read\write\delete files in lock directory // in case of any error just log it and don't stop engine execution void adjustLockDirectoryAccess(const char* pathname) { PSECURITY_DESCRIPTOR pSecDesc = NULL; PSID pSID_Users = NULL; PSID pSID_Administrators = NULL; PACL pNewACL = NULL; try { // We should pass root directory in format "C:\" into GetVolumeInformation(). // In case of pathname is not local folder (i.e. \\share\folder) let // GetVolumeInformation() return an error. Firebird::PathName root(pathname); const Firebird::PathName::size_type pos = root.find(':', 0); if (pos == 1) { root.erase(pos + 1, root.length()); PathUtils::ensureSeparator(root); } DWORD fsflags; if (!GetVolumeInformation(root.c_str(), NULL, 0, NULL, NULL, &fsflags, NULL, 0)) Firebird::system_error::raise("GetVolumeInformation"); if (!(fsflags & FS_PERSISTENT_ACLS)) return; // Adjust security for our new folder : allow BUILTIN\Users group to // read\write\delete files PACL pOldACL = NULL; if (GetNamedSecurityInfo((LPSTR) pathname, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldACL, NULL, &pSecDesc) != ERROR_SUCCESS) { Firebird::system_error::raise("GetNamedSecurityInfo"); } SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY; if (!AllocateAndInitializeSid(&sidAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &pSID_Users)) { Firebird::system_error::raise("AllocateAndInitializeSid"); } if (!AllocateAndInitializeSid(&sidAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSID_Administrators)) { Firebird::system_error::raise("AllocateAndInitializeSid"); } EXPLICIT_ACCESS eas[2]; memset(eas, 0, sizeof(eas)); eas[0].grfAccessPermissions = FILE_GENERIC_READ | FILE_GENERIC_WRITE | DELETE; eas[0].grfAccessMode = GRANT_ACCESS; eas[0].grfInheritance = SUB_OBJECTS_ONLY_INHERIT; eas[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; eas[0].Trustee.TrusteeType = TRUSTEE_IS_GROUP; eas[0].Trustee.ptstrName = (LPSTR) pSID_Users; eas[1].grfAccessPermissions = FILE_GENERIC_READ | FILE_GENERIC_WRITE | DELETE; eas[1].grfAccessMode = GRANT_ACCESS; eas[1].grfInheritance = SUB_OBJECTS_ONLY_INHERIT; eas[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; eas[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; eas[1].Trustee.ptstrName = (LPSTR) pSID_Administrators; if (SetEntriesInAcl(2, eas, pOldACL, &pNewACL) != ERROR_SUCCESS) Firebird::system_error::raise("SetEntriesInAcl"); if (SetNamedSecurityInfo((LPSTR) pathname, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pNewACL, NULL) != ERROR_SUCCESS) { Firebird::system_error::raise("SetNamedSecurityInfo"); } } catch (const Firebird::Exception& ex) { Firebird::string str; str.printf("Error adjusting access rights for folder \"%s\" :", pathname); iscLogException(str.c_str(), ex); } if (pSID_Users) { FreeSid(pSID_Users); } if (pSID_Administrators) { FreeSid(pSID_Administrators); } if (pNewACL) { LocalFree(pNewACL); } if (pSecDesc) { LocalFree(pSecDesc); } }