8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-26 07:23:08 +01:00
firebird-mirror/src/jrd/isc.cpp

580 lines
12 KiB
C++
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: JRD Access Method
* MODULE: isc.cpp
2001-05-23 15:26:42 +02:00
* DESCRIPTION: General purpose but non-user routines.
*
* The contents of this file are subject to the Interbase Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy
* of the License at http://www.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
* or implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code was created by Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
2002-07-02 11:49:19 +02:00
*
2001-05-23 15:26:42 +02:00
* Solaris x86 changes - Konstantin Kuznetsov, Neil McCalden
2002-07-02 11:49:19 +02:00
* 26-Sept-2001 Paul Beach - External File Directory Config. Parameter
* 17-Oct-2001 Mike Nordell: CPU affinity
* 01-Feb-2002 Paul Reeves: Removed hard-coded registry path
2002-10-29 03:45:09 +01:00
*
* 2002.10.28 Sean Leyne - Completed removal of obsolete "DGUX" port
*
2002-10-30 07:40:58 +01:00
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
*
* 2002.10.30 Sean Leyne - Removed support for obsolete "PC_PLATFORM" define
2002-10-31 06:33:35 +01:00
* 2002.10.30 Sean Leyne - Code Cleanup, removed obsolete "SUN3_3" port
*
2001-05-23 15:26:42 +02:00
*/
2006-02-23 06:22:08 +01:00
2001-12-24 03:51:06 +01:00
#ifdef DARWIN
#define _STLP_CCTYPE
#endif
2001-05-23 15:26:42 +02:00
#include "firebird.h"
2004-04-29 00:36:29 +02:00
#include <stdio.h>
2001-05-23 15:26:42 +02:00
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "../jrd/common.h"
#include "gen/iberror.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/ibase.h"
#include "../jrd/jrd.h"
#include "../jrd/scl.h"
#include "../jrd/gds_proto.h"
#include "../jrd/isc_proto.h"
#include "../jrd/jrd_proto.h"
#include "../common/classes/init.h"
2001-05-23 15:26:42 +02:00
#ifdef SOLARIS
#include <sys/utsname.h>
#endif
/* Win32 specific stuff */
#ifdef WIN_NT
#include <windows.h>
#include <aclapi.h>
2007-11-19 21:34:10 +01:00
#include <lmcons.h>
class SecurityAttributes
{
public:
explicit SecurityAttributes(MemoryPool& pool)
: m_pool(pool)
{
// Ensure that our process has the SYNCHRONIZE privilege granted to everyone
2008-04-12 13:57:46 +02:00
PSECURITY_DESCRIPTOR pOldSD = NULL;
PACL pOldACL = NULL;
2008-12-20 09:12:19 +01:00
GetSecurityInfo(GetCurrentProcess(), SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
NULL, NULL, &pOldACL, NULL, &pOldSD);
2008-04-11 03:38:50 +02:00
// NULL pOldACL means all privileges. If we assign pNewACL in this case
// we'll lost all privileges except assigned SYNCHRONIZE
2008-12-02 08:09:49 +01:00
if (pOldACL)
{
2008-04-11 03:38:50 +02:00
SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_WORLD_SID_AUTHORITY;
PSID pSID = NULL;
2008-04-11 03:38:50 +02:00
AllocateAndInitializeSid(&sidAuth, 1, SECURITY_WORLD_RID,
0, 0, 0, 0, 0, 0, 0, &pSID);
EXPLICIT_ACCESS ea;
memset(&ea, 0, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = SYNCHRONIZE;
ea.grfAccessMode = GRANT_ACCESS;
ea.grfInheritance = NO_INHERITANCE;
ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea.Trustee.ptstrName = (LPTSTR) pSID;
PACL pNewACL = NULL;
SetEntriesInAcl(1, &ea, pOldACL, &pNewACL);
2008-12-20 09:12:19 +01:00
SetSecurityInfo(GetCurrentProcess(), SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION,
NULL, NULL, pNewACL, NULL);
if (pSID) {
FreeSid(pSID);
}
if (pNewACL) {
LocalFree(pNewACL);
}
}
if (pOldSD) {
LocalFree(pOldSD);
}
// Create and initialize the default security descriptor
// to be assigned to various IPC objects.
//
// WARNING!!! The absent DACL means full access granted
// to everyone, this is a huge security risk!
PSECURITY_DESCRIPTOR p_security_desc = static_cast<PSECURITY_DESCRIPTOR>(
2009-03-01 16:42:23 +01:00
pool.allocate(SECURITY_DESCRIPTOR_MIN_LENGTH));
attributes.nLength = sizeof(attributes);
attributes.lpSecurityDescriptor = p_security_desc;
attributes.bInheritHandle = TRUE;
if (!InitializeSecurityDescriptor(p_security_desc, SECURITY_DESCRIPTOR_REVISION) ||
!SetSecurityDescriptorDacl(p_security_desc, TRUE, NULL, FALSE))
{
pool.deallocate(p_security_desc);
attributes.lpSecurityDescriptor = NULL;
}
}
~SecurityAttributes()
{
if (attributes.lpSecurityDescriptor)
m_pool.deallocate(attributes.lpSecurityDescriptor);
}
operator LPSECURITY_ATTRIBUTES()
{
return attributes.lpSecurityDescriptor ? &attributes : NULL;
}
private:
SECURITY_ATTRIBUTES attributes;
MemoryPool& m_pool;
};
static Firebird::InitInstance<SecurityAttributes> security_attributes;
#endif // WIN_NT
2001-05-23 15:26:42 +02:00
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#ifdef HAVE_CTYPE_H
#include <ctype.h>
#endif
2001-05-23 15:26:42 +02:00
/* Unix specific stuff */
#if defined(UNIX)
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
2003-02-19 07:14:39 +01:00
#ifdef HAVE_PWD_H
2001-05-23 15:26:42 +02:00
#include <pwd.h>
2003-02-19 07:14:39 +01:00
#endif
#ifdef HAVE_UNISTD_H
2001-05-23 15:26:42 +02:00
#include <unistd.h>
#endif
2003-02-19 13:54:39 +01:00
#endif
2001-05-23 15:26:42 +02:00
#ifndef O_RDWR
#include <fcntl.h>
#endif
2008-02-13 17:47:34 +01:00
bool ISC_check_process_existence(SLONG pid)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* I S C _ c h e c k _ p r o c e s s _ e x i s t e n c e
*
**************************************
*
* Functional description
* Return TRUE if the indicated process
* exists. FALSE otherwise.
*
**************************************/
2008-02-13 17:47:34 +01:00
#ifdef WIN_NT
const HANDLE handle = OpenProcess(SYNCHRONIZE, FALSE, (DWORD) pid);
if (!handle)
{
return (GetLastError() == ERROR_ACCESS_DENIED);
}
const bool alive = (WaitForSingleObject(handle, 0) != WAIT_OBJECT_0);
CloseHandle(handle);
return alive;
2001-05-23 15:26:42 +02:00
#else
2008-02-13 17:47:34 +01:00
return (kill((int) pid, 0) == -1 && errno == ESRCH) ? false : true;
2001-05-23 15:26:42 +02:00
#endif
}
2009-04-15 08:29:00 +02:00
#if defined(SOLARIS)
2004-05-29 15:34:54 +02:00
TEXT* ISC_get_host(TEXT* string, USHORT length)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* I S C _ g e t _ h o s t ( S O L A R I S )
*
**************************************
*
* Functional description
* Get host name.
*
**************************************/
struct utsname name;
if (uname(&name) >= 0)
{
2001-05-23 15:26:42 +02:00
strncpy(string, name.nodename, length);
string[length - 1] = 0;
}
2001-05-23 15:26:42 +02:00
else
strcpy(string, "local");
return string;
}
#elif defined(WIN_NT)
2001-05-23 15:26:42 +02:00
2004-05-29 15:34:54 +02:00
TEXT* ISC_get_host(TEXT* string, USHORT length)
{
/**************************************
*
* I S C _ g e t _ h o s t ( W I N _ N T )
*
**************************************
*
* Functional description
* Get host name.
* Note that this is not the DNS (TCP/IP) hostname,
* it's the Win32 computer name.
*
**************************************/
DWORD host_len = length;
if (GetComputerName(string, &host_len))
{
string[host_len] = 0;
}
else
{
strcpy(string, "local");
}
return string;
}
#else
2004-05-29 15:34:54 +02:00
TEXT* ISC_get_host(TEXT* string, USHORT length)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* I S C _ g e t _ h o s t ( G E N E R I C )
*
**************************************
*
* Functional description
* Get host name.
*
**************************************/
// See http://www.opengroup.org/onlinepubs/007908799/xns/gethostname.html
if (gethostname(string, length))
string[0] = 0; // failure
else
string[length - 1] = 0; // truncation doesn't guarantee null termination
2001-05-23 15:26:42 +02:00
return string;
}
#endif
const TEXT* ISC_get_host(Firebird::string& host)
{
/**************************************
*
* I S C _ g e t _ h o s t
*
**************************************
*
* Functional description
* Get host name in non-plain buffer.
*
**************************************/
TEXT buffer[BUFFER_SMALL];
ISC_get_host(buffer, sizeof(buffer));
host = buffer;
return host.c_str();
}
2001-05-23 15:26:42 +02:00
#ifdef UNIX
2008-12-02 08:09:49 +01:00
bool ISC_get_user(Firebird::string* name,
int* id,
int* group,
const TEXT* user_string)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* I S C _ g e t _ u s e r ( U N I X )
*
**************************************
*
* Functional description
* Find out who the user is.
*
**************************************/
/* egid and euid need to be signed, uid_t is unsigned on SUN! */
SLONG egid, euid;
TEXT user_name[256];
const TEXT* p = 0;
2001-05-23 15:26:42 +02:00
if (user_string && *user_string) {
const TEXT* q = user_string;
2009-06-04 15:15:41 +02:00
char* un = user_name;
while ((*un = *q++) && *un != '.')
++un;
*un = 0;
2001-05-23 15:26:42 +02:00
p = user_name;
egid = euid = -1;
#ifdef TRUST_CLIENT_VERIFICATION
2001-05-23 15:26:42 +02:00
if (*q) {
egid = atoi(q);
while (*q && (*q != '.'))
q++;
if (*q == '.') {
q++;
euid = atoi(q);
}
}
#endif
2001-05-23 15:26:42 +02:00
}
else {
euid = (SLONG) geteuid();
egid = (SLONG) getegid();
const struct passwd* password = getpwuid(euid);
if (password)
p = password->pw_name;
2001-05-23 15:26:42 +02:00
else
p = "";
endpwent();
}
if (name)
*name = p;
2001-05-23 15:26:42 +02:00
if (id)
*id = euid;
if (group)
*group = egid;
return (euid == 0);
}
#endif
#ifdef WIN_NT
2008-12-02 08:09:49 +01:00
bool ISC_get_user(Firebird::string* name,
int* id,
int* group,
2009-04-26 12:24:44 +02:00
const TEXT* /*user_string*/)
{
/**************************************
*
* I S C _ g e t _ u s e r ( W I N _ N T )
*
**************************************
*
* Functional description
* Find out who the user is.
*
**************************************/
if (id)
*id = -1;
if (group)
*group = -1;
if (name)
{
2007-11-19 21:34:10 +01:00
DWORD name_len = UNLEN;
TEXT* nm = name->getBuffer(name_len + 1);
if (GetUserName(nm, &name_len))
{
nm[name_len] = 0;
2006-12-08 19:38:15 +01:00
// NT user name is case insensitive
2007-11-19 21:34:10 +01:00
CharUpperBuff(nm, name_len);
name->recalculate_length();
}
else
{
*name = "";
}
}
2006-12-08 19:38:15 +01:00
return false;
}
2006-12-08 19:38:15 +01:00
#endif //WIN_NT
inline void setPrefixIfNotEmpty(const Firebird::PathName& prefix, SSHORT arg_type)
{
/**************************************
*
* s e t P r e f i x I f N o t E m p t y
*
**************************************
*
* Functional description
* Helper for ISC_set_prefix
*
**************************************/
2008-12-02 08:09:49 +01:00
if (prefix.hasData())
{
2008-12-02 08:09:49 +01:00
// ignore here return value of gds__get_prefix():
// it will never fail with our good arguments
gds__get_prefix(arg_type, prefix.c_str());
}
}
SLONG ISC_set_prefix(const TEXT* sw, const TEXT* path)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
2008-12-02 08:09:49 +01:00
* i s c _ s e t _ p r e f i x
2001-05-23 15:26:42 +02:00
*
**************************************
*
* Functional description
* Parse the 'E' argument further for 'EL' 'EM' or 'E'
2001-05-23 15:26:42 +02:00
*
**************************************/
2008-12-02 08:09:49 +01:00
/*
* We can't call gds__get_prefix() at once when switch is found.
2008-12-02 08:09:49 +01:00
* gds__get_prefix() invokes gdsPrefixInit(), which in turn causes
* config file to be loaded. And in case when -el or -em is given
* before -e, this leads to use of wrong firebird.conf.
2008-12-02 08:09:49 +01:00
* To avoid it accumulate values for switches locally,
* and finally when called with sw==0, use them in correct order.
*/
2008-03-11 03:05:09 +01:00
static struct ESwitches
{
Firebird::PathName prefix, lockPrefix, msgPrefix;
2008-03-11 03:05:09 +01:00
explicit ESwitches(MemoryPool& p)
: prefix(p), lockPrefix(p), msgPrefix(p)
{
}
}* eSw = 0;
2008-12-02 08:09:49 +01:00
if (! sw)
{
if (eSw)
{
setPrefixIfNotEmpty(eSw->prefix, IB_PREFIX_TYPE);
setPrefixIfNotEmpty(eSw->lockPrefix, IB_PREFIX_LOCK_TYPE);
setPrefixIfNotEmpty(eSw->msgPrefix, IB_PREFIX_MSG_TYPE);
delete eSw;
eSw = 0;
}
return 0;
}
2008-12-02 08:09:49 +01:00
if ((!path) || (path[0] <= ' '))
{
return -1;
}
2001-05-23 15:26:42 +02:00
if (! eSw)
{
eSw = FB_NEW(*getDefaultMemoryPool()) ESwitches(*getDefaultMemoryPool());
}
2008-12-02 08:09:49 +01:00
switch (UPPER(*sw))
{
2001-05-23 15:26:42 +02:00
case '\0':
eSw->prefix = path;
2001-05-23 15:26:42 +02:00
break;
case 'L':
eSw->lockPrefix = path;
2001-05-23 15:26:42 +02:00
break;
case 'M':
eSw->msgPrefix = path;
2001-05-23 15:26:42 +02:00
break;
default:
return -1;
2001-05-23 15:26:42 +02:00
}
return 0;
2001-05-23 15:26:42 +02:00
}
#ifdef WIN_NT
LPSECURITY_ATTRIBUTES ISC_get_security_desc()
{
return security_attributes();
}
#endif
void iscLogStatus(const TEXT* text, const ISC_STATUS* status_vector)
{
/**************************************
*
* g d s _ $ l o g _ s t a t u s
*
**************************************
*
* Functional description
* Log error to error log.
*
**************************************/
fb_assert(status_vector[1] != FB_SUCCESS);
try
{
Firebird::string buffer(text ? text : "");
TEXT temp[BUFFER_LARGE];
while (fb_interpret(temp, sizeof(temp), &status_vector))
{
2008-09-06 20:42:55 +02:00
if (!buffer.isEmpty())
{
buffer += "\n\t";
}
buffer += temp;
}
gds__log("%s", buffer.c_str());
}
catch (const Firebird::Exception&)
{} // no-op
}
void iscLogException(const char* text, const Firebird::Exception& e)
{
/**************************************
*
* l o g E x c e p t i o n
*
**************************************
*
* Functional description
* Add record about an exception to firebird.log
*
**************************************/
ISC_STATUS_ARRAY s;
e.stuff_exception(s);
iscLogStatus(text, s);
}