Ejemplo n.º 1
0
static PSECURITY_DESCRIPTOR s_GetFileSecurityDescriptor(const string& path)
{
    if ( path.empty() ) {
        CNcbiError::Set(CNcbiError::eInvalidArgument);
        return NULL;
    }
    PSECURITY_DESCRIPTOR sd = NULL;
    DWORD size              = 0;
    DWORD size_need         = 0;

    if ( !GetFileSecurity(_T_XCSTRING(path), FILE_SECURITY_INFO, sd, size, &size_need) ) {
        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
            CNcbiError::SetFromWindowsError();
            return NULL;
        }
        // Allocate memory for the buffer
        sd = (PSECURITY_DESCRIPTOR) LocalAlloc(LMEM_FIXED, size_need);
        if ( !sd ) {
            CNcbiError::SetFromWindowsError();
            return NULL;
        }
        size = size_need;
        if ( !GetFileSecurity(_T_XCSTRING(path), FILE_SECURITY_INFO,
                              sd, size, &size_need) ) {
            CNcbiError::SetFromWindowsError();
            LocalFree((HLOCAL) sd);
            return NULL;
        }
    }
    return sd;
}
Ejemplo n.º 2
0
void CInterProcessLock::Remove()
{
    if (m_Handle != kInvalidLockHandle) {
        Unlock();
    }
    NcbiSys_unlink(_T_XCSTRING(m_SystemName));
}
Ejemplo n.º 3
0
extern void DoThrowTraceAbort(void)
{
    if ( !s_DTTA_Initialized ) {
        const TXChar* str = NcbiSys_getenv(_T_XCSTRING(ABORT_ON_THROW));
        if (str  &&  *str)
            s_DoThrowTraceAbort = true;
        s_DTTA_Initialized  = true;
    }

    if ( s_DoThrowTraceAbort )
        abort();
}
Ejemplo n.º 4
0
bool CWinSecurity::GetObjectOwner(const string&  obj_name,
                                  SE_OBJECT_TYPE obj_type,
                                  string* owner, string* group,
                                  unsigned int* uid, unsigned int* gid)
{
    PSID sid_owner;
    PSID sid_group;
    PSECURITY_DESCRIPTOR sd;

    DWORD res = GetNamedSecurityInfo(_T_XCSTRING(obj_name), obj_type,
                                     ACCOUNT_SECURITY_INFO,
                                     &sid_owner, &sid_group, NULL, NULL, &sd );
    if ( res != ERROR_SUCCESS ) {
        CNcbiError::SetWindowsError(res);
        return false;
    }
    bool retval = s_GetOwnerGroupFromSIDs(sid_owner, sid_group, owner, group, uid, gid);
    LocalFree(sd);
    return retval;
}
Ejemplo n.º 5
0
bool CWinSecurity::SetFileOwner(const string& filename,
                                const string& owner, const string& group, 
                                unsigned int* uid, unsigned int* gid)
{
    if ( uid ) *uid = 0;
    if ( gid ) *gid = 0;

    if ( owner.empty()  &&  group.empty() ) {
        CNcbiError::Set(CNcbiError::eInvalidArgument);
        return false;
    }

    HANDLE  token     = INVALID_HANDLE_VALUE;
    PSID    owner_sid = NULL;
    PSID    group_sid = NULL;
    bool    success   = false;

    // Get SIDs for new owner and group
    if ( !owner.empty() ) {
        owner_sid = x_GetAccountSidByName(owner, SidTypeUser);
        if (!owner_sid) {
            return false;
        }
    }
    if ( !group.empty() ) {
        group_sid = x_GetAccountSidByName(group, SidTypeGroup);
        if (!group_sid) {
            goto cleanup;
        }
    }
    if (uid || gid) {
        s_GetOwnerGroupFromSIDs(owner_sid, group_sid, NULL, NULL, uid, gid);
    }

    // Change owner

    SECURITY_INFORMATION security_info = 0;
    if ( owner_sid ) {
        security_info |= OWNER_SECURITY_INFORMATION;
    }
    if ( group_sid ) {
        security_info |= GROUP_SECURITY_INFORMATION;
    }

    // Set new owner/group in the object's security descriptor
    if ( SetNamedSecurityInfo((TXChar*)_T_XCSTRING(filename),
                              SE_FILE_OBJECT, security_info,
                              owner_sid, group_sid, NULL, NULL) == ERROR_SUCCESS ) {
        success = true;
        goto cleanup;
    }

    // If the previous call failed because access was denied,
    // enable the necessary admin privileges for the current thread and try again.

    token = s_GetThreadToken(TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY);
    if ( token == INVALID_HANDLE_VALUE) {
        goto cleanup;
    }
    bool prev_ownership_name;
    bool prev_restore_name;

    if ( !SetTokenPrivilege(token, SE_TAKE_OWNERSHIP_NAME, true, &prev_ownership_name) ||
         !SetTokenPrivilege(token, SE_RESTORE_NAME, true, &prev_restore_name) ) {
        goto cleanup;
    }
    if ( SetNamedSecurityInfo((TXChar*)_T_XCSTRING(filename),
                              SE_FILE_OBJECT, security_info,
                              owner_sid, group_sid, NULL, NULL) == ERROR_SUCCESS ) {
        success = true;
    }
    // Restore privileges
    SetTokenPrivilege(token, SE_TAKE_OWNERSHIP_NAME, prev_ownership_name);
    SetTokenPrivilege(token, SE_RESTORE_NAME, prev_restore_name);


cleanup:
    if ( owner_sid ) LocalFree(owner_sid);
    if ( group_sid ) LocalFree(group_sid);
    if ( token != INVALID_HANDLE_VALUE) CloseHandle(token);

    return success;
}
Ejemplo n.º 6
0
void CInterProcessLock::Lock(const CTimeout& timeout,
                             const CTimeout& granularity)
{
    CFastMutexGuard LOCK(s_ProcessLock);

    // Check that lock with specified name not already locked
    // in the current process.
    TLocks::iterator it = s_Locks->find(m_SystemName);

    if (m_Handle != kInvalidLockHandle) {
        // The lock is already set in this CInterProcessLock object,
        // just increase reference counter.
        _VERIFY(it != s_Locks->end());
        it->second++;
        return;
    } else {
        if (it != s_Locks->end()) {
            // The lock already exists in the current process.
            // We can use one CInterProcessLock object with
            // multiple Lock() calls, but not with different
            // CInterProcessLock objects. For example, on MS-Windows,
            // we cannot wait on the same mutex in the same thread.
            // So, two different objects can set locks simultaneously.
            // And for OS-compatibility we can do nothing here,
            // except throwing an exception.
            NCBI_THROW(CInterProcessLockException, eMultipleLocks,
                       "Attempt to lock already locked object " \
                       "in the same process");
        }
    }

    // Try to acquire a lock with specified timeout

#if defined(NCBI_OS_UNIX)

    // Open lock file
    mode_t perm = CDirEntry::MakeModeT(
        CDirEntry::fRead | CDirEntry::fWrite /* user */,
        CDirEntry::fRead | CDirEntry::fWrite /* group */,
        0, 0 /* other & special */);
    int fd = open(m_SystemName.c_str(), O_CREAT | O_RDWR, perm);
    if (fd == -1) {
        NCBI_THROW(CInterProcessLockException, eCreateError,
                   string("Error creating lockfile ") + m_SystemName + 
                   ": " + strerror(errno));
    }

    // Try to acquire the lock
    
    int x_errno = 0;
    
    if (timeout.IsInfinite()  ||  timeout.IsDefault()) {
        while ((x_errno = s_UnixLock(fd))) {
            if (errno != EAGAIN)
                break;
        }

    } else {
        unsigned long ms = timeout.GetAsMilliSeconds();
        if ( !ms ) {
            // Timeout == 0
            x_errno = s_UnixLock(fd);
        } else {
            // Timeout > 0
            unsigned long ms_gran;
            if ( granularity.IsInfinite()  ||
                 granularity.IsDefault() ) 
            {
                ms_gran = min(ms/5, (unsigned long)500);
            } else {
                ms_gran = granularity.GetAsMilliSeconds();
            }
            // Try to lock within specified timeout
            for (;;) {
                x_errno = s_UnixLock(fd);
                if ( !x_errno ) {
                    // Successfully locked
                    break;
                }
                if (x_errno != EACCES  &&
                    x_errno != EAGAIN ) {
                    // Error
                    break;
                }
                // Otherwise -- sleep granularity timeout
                unsigned long ms_sleep = ms_gran;
                if (ms_sleep > ms) {
                    ms_sleep = ms;
                }
                if ( !ms_sleep ) {
                     break;
                }
                SleepMilliSec(ms_sleep);
                ms -= ms_sleep;
            }
            // Timeout
            if ( !ms ) {
                close(fd);
                NCBI_THROW(CInterProcessLockException, eLockTimeout,
                           "The lock could not be acquired in the time " \
                           "allotted");
            }
        } // if (!ms)
    } // if (timeout.IsInfinite())
    
    // Error
    if ( x_errno ) {
        close(fd);
        NCBI_THROW(CInterProcessLockException, eLockError,
                   "Error creating lock");
    }
    // Success
    m_Handle = fd;

#elif defined(NCBI_OS_MSWIN)

    HANDLE  handle  = ::CreateMutex(NULL, TRUE, _T_XCSTRING(m_SystemName));
    errno_t errcode = ::GetLastError();
    if (handle == kInvalidLockHandle) {
        switch(errcode) {
            case ERROR_ACCESS_DENIED:
                // Mutex with specified name already exists, 
                // but we don't have enough rights to open it.
                NCBI_THROW(CInterProcessLockException, eLockError,
                           "The lock already exists");
                break;
            case ERROR_INVALID_HANDLE:
                // Some system object with the same name already exists
                NCBI_THROW(CInterProcessLockException, eLockError,
                           "Error creating lock, system object with the same" \
                           "name already exists");
                break;
            default:
                // Unknown error
                NCBI_THROW(CInterProcessLockException, eCreateError,
                           "Error creating lock");
                break;
        }
    } else {
        // Mutex with specified name already exists
        if (errcode == ERROR_ALREADY_EXISTS) {
            // Wait
            DWORD res;
            if (timeout.IsInfinite()  ||  timeout.IsDefault()) {
                res = WaitForSingleObject(handle, INFINITE);
            } else {
                res = WaitForSingleObject(handle, timeout.GetAsMilliSeconds());
            }
            switch(res) {
                case WAIT_OBJECT_0:
                    // The lock has been acquired
                    break;
                case WAIT_TIMEOUT:
                    ::CloseHandle(handle);
                    NCBI_THROW(CInterProcessLockException, eLockTimeout,
                               "The lock could not be acquired in the time " \
                               "allotted");
                    break;
                case WAIT_ABANDONED:
                    // The lock is in abandoned state... Other thread/process
                    // owning it was terminated. We can reuse this mutex, but 
                    // it is better to wait until it will be released by OS.
                    /* FALLTHRU */
                default:
                    ::CloseHandle(handle);
                    NCBI_THROW(CInterProcessLockException, eLockError,
                               "Error creating lock");
                    break;
            }
        }
        m_Handle = handle;
    }
#endif
    // Set reference counter to 1
    (*s_Locks)[m_SystemName] = 1;
}