static NTSTATUS ValidateModuleTable( PLW_SVCM_MODULE pTable, PCSTR pPath ) { NTSTATUS status = STATUS_SUCCESS; if (!pTable) { LW_RTL_LOG_ERROR( "Service module '%s' did not provide a function table", pPath); status = STATUS_BAD_DLL_ENTRYPOINT; GCOS(status); } if (pTable->Size < sizeof(*pTable) || !pTable->Init || !pTable->Destroy || !pTable->Start || !pTable->Stop) { LW_RTL_LOG_ERROR( "Service module '%s' has a bogus function table", pPath); status = STATUS_BAD_DLL_ENTRYPOINT; GCOS(status); } cleanup: return status; }
static DWORD LsaPstorepInitializePlugin( OUT PLSA_PSTORE_PLUGIN_INFO PluginInfo, IN PCSTR PluginName ) { DWORD dwError = 0; int EE = 0; LSA_PSTORE_PLUGIN_INITIALIZE_FUNCTION initFunction = NULL; dwError = LwNtStatusToWin32Error(LwRtlCStringDuplicate(&PluginInfo->Name, PluginName)); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); dwError = LsaPstorepGetPluginPath(PluginInfo->Name, &PluginInfo->Path); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); dwError = LsaPstorepOpenPlugin( PluginInfo->Path, LSA_PSTORE_PLUGIN_INITIALIZE_FUNCTION_NAME, &PluginInfo->LibraryHandle, OUT_PPVOID(&initFunction)); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); dwError = initFunction(LSA_PSTORE_PLUGIN_VERSION, PluginInfo->Name, &PluginInfo->Dispatch, &PluginInfo->Context); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); if (!PluginInfo->Dispatch) { LW_RTL_LOG_ERROR("LSA pstore plugin %s is missing a dispatch table", PluginInfo->Name); dwError = ERROR_DLL_INIT_FAILED; GOTO_CLEANUP_EE(EE); } if (!PluginInfo->Dispatch->Cleanup) { LW_RTL_LOG_ERROR("LSA pstore plugin %s is missing the Cleanup function", PluginInfo->Name); dwError = ERROR_DLL_INIT_FAILED; GOTO_CLEANUP_EE(EE); } LW_RTL_LOG_VERBOSE("Loaded LSA pstore plugin %s from %s", PluginInfo->Name, PluginInfo->Path); cleanup: if (dwError) { LsaPstorepCleanupPlugin(PluginInfo); } LSA_PSTORE_LOG_LEAVE_ERROR_EE(dwError, EE); return dwError; }
DWORD LwLdapBindDirectorySasl( LDAP *ld, PCSTR pszServerName, BOOLEAN bSeal ) { DWORD dwError = LW_ERROR_SUCCESS; // Do not attempt to canonicalize the server // name which isn't necessary since we used // the server's FQDN or address. dwError = ldap_set_option( ld, LDAP_OPT_X_SASL_NOCANON, LDAP_OPT_ON); BAIL_ON_LDAP_ERROR(dwError); // ssf=1 is sign, ssf>1 is seal. By default // it will use the maximum available ssf level // so setting minssf isn't strictly necessary. // Setting minssf guarantees an error if it // cannot provide the minimum level. if (bSeal) { dwError = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS, (void *)"minssf=2"); BAIL_ON_LDAP_ERROR(dwError); } else { dwError = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS, (void *)"minssf=1,maxssf=1"); BAIL_ON_LDAP_ERROR(dwError); } dwError = ldap_sasl_interactive_bind_s( ld, NULL, "GSS-SPNEGO", NULL, NULL, LDAP_SASL_QUIET, LwLdapGssSpnegoInteract, (void *)pszServerName); if (dwError != 0) { LW_RTL_LOG_ERROR("ldap_sasl_interactive_bind_s failed with error code %d", dwError); BAIL_ON_LDAP_ERROR(dwError); } error: return dwError; }
DWORD LwLdapBindDirectoryAnonymous( HANDLE hDirectory ) { DWORD dwError = 0; PLW_LDAP_DIRECTORY_CONTEXT pDirectory = (PLW_LDAP_DIRECTORY_CONTEXT)hDirectory; LW_BAIL_ON_INVALID_HANDLE(hDirectory); dwError = ldap_bind_s( pDirectory->ld, NULL, NULL, LDAP_AUTH_SIMPLE); BAIL_ON_LDAP_ERROR(dwError); cleanup: return dwError; error: LW_RTL_LOG_ERROR("Failed on LDAP simple bind (Error code: %u)", dwError); if(pDirectory->ld != NULL) { ldap_unbind_s(pDirectory->ld); pDirectory->ld = NULL; } goto cleanup; }
LW_DWORD LwMapHErrnoToLwError( LW_IN LW_DWORD dwHErrno ) { switch(dwHErrno) { case 0: return LW_ERROR_SUCCESS; case HOST_NOT_FOUND: return WSAHOST_NOT_FOUND; case NO_DATA: #if defined(NO_ADDRESS) && NO_DATA != NO_ADDRESS case NO_ADDRESS: #endif return WSANO_DATA; case NO_RECOVERY: return WSANO_RECOVERY; case TRY_AGAIN: return WSATRY_AGAIN; default: LW_RTL_LOG_ERROR("Unable to map h_errno %d", dwHErrno); return LW_ERROR_UNKNOWN; } }
static NTSTATUS LwRtlSvcmInitializeInstance( PLW_SVCM_INSTANCE pInstance, PCWSTR pServiceName, PCSTR pModuleName, LW_SVCM_MODULE_ENTRY_FUNCTION Entry ) { NTSTATUS status = STATUS_SUCCESS; pInstance->pTable = Entry(); status = ValidateModuleTable(pInstance->pTable, pModuleName); GCOS(status); status = pInstance->pTable->Init(pServiceName, pInstance); if (status) { LW_RTL_LOG_ERROR( "Could not initialize service module '%s': %s (0x%lx)", pModuleName, LwNtStatusToName(status), (unsigned long) status); } GCOS(status); cleanup: return status; }
DWORD LwMapLwmsgStatusToLwError( LWMsgStatus status ) { switch (status) { case LWMSG_STATUS_SUCCESS: return LW_ERROR_SUCCESS; case LWMSG_STATUS_ERROR: return LW_ERROR_INTERNAL; case LWMSG_STATUS_MEMORY: case LWMSG_STATUS_RESOURCE_LIMIT: return LW_ERROR_OUT_OF_MEMORY; case LWMSG_STATUS_MALFORMED: case LWMSG_STATUS_OVERFLOW: case LWMSG_STATUS_UNDERFLOW: case LWMSG_STATUS_EOF: return LW_ERROR_INVALID_MESSAGE; case LWMSG_STATUS_INVALID_PARAMETER: return LW_ERROR_INVALID_PARAMETER; case LWMSG_STATUS_INVALID_STATE: return LW_ERROR_INVALID_PARAMETER; case LWMSG_STATUS_UNIMPLEMENTED: return LW_ERROR_NOT_IMPLEMENTED; case LWMSG_STATUS_SYSTEM: return LW_ERROR_INTERNAL; case LWMSG_STATUS_TIMEOUT: return LW_ERROR_ERRNO_ETIMEDOUT; case LWMSG_STATUS_SECURITY: return LW_ERROR_ACCESS_DENIED; case LWMSG_STATUS_CANCELLED: return LW_ERROR_INTERRUPTED; case LWMSG_STATUS_FILE_NOT_FOUND: return ERROR_FILE_NOT_FOUND; case LWMSG_STATUS_CONNECTION_REFUSED: return LW_ERROR_ERRNO_ECONNREFUSED; case LWMSG_STATUS_PEER_RESET: return LW_ERROR_ERRNO_ECONNRESET; case LWMSG_STATUS_PEER_ABORT: return LW_ERROR_ERRNO_ECONNABORTED; case LWMSG_STATUS_PEER_CLOSE: case LWMSG_STATUS_SESSION_LOST: return LW_ERROR_ERRNO_EPIPE; case LWMSG_STATUS_INVALID_HANDLE: return ERROR_INVALID_HANDLE; default: LW_RTL_LOG_ERROR("Unable to map lwmsg status %d", status); return LW_ERROR_INTERNAL; } }
DWORD InstallLwiCompat( PCSTR pSmbdPath ) { DWORD error = 0; PSTR pSambaDir = NULL; PSTR pLwiCompat = NULL; PCSTR pLikewiseLwiCompat = LIBDIR "/" LWICOMPAT_FILENAME; error = GetIdmapDir( pSmbdPath, &pSambaDir); BAIL_ON_LSA_ERROR(error); error = LwAllocateStringPrintf( &pLwiCompat, "%s/%s", pSambaDir, LWICOMPAT_FILENAME ); BAIL_ON_LSA_ERROR(error); if (unlink(pLwiCompat) < 0) { if (errno != ENOENT) { error = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(error); } } if (symlink(pLikewiseLwiCompat, pLwiCompat) < 0) { error = LwMapErrnoToLwError(errno); if (error == ERROR_FILE_NOT_FOUND) { LW_RTL_LOG_ERROR("Cannot access idmap directory %s. Please ensure you have winbind installed", pSambaDir); } BAIL_ON_LSA_ERROR(error); } LW_RTL_LOG_INFO("Linked idmapper %s to %s", pLwiCompat, pLikewiseLwiCompat); cleanup: LW_SAFE_FREE_STRING(pSambaDir); LW_SAFE_FREE_STRING(pLwiCompat); return error; }
static PVOID EventThread( PVOID pContext ) { NTSTATUS status = STATUS_SUCCESS; status = EventLoop((PEPOLL_THREAD) pContext); if (!NT_SUCCESS(status)) { LW_RTL_LOG_ERROR( "Task thread exiting with fatal error: %s (0x%x)", LwNtStatusToName(status), status); abort(); } return NULL; }
// This utility function parse a ldap result in the format of // <GUID=xxxxxxxx>;<SID=yyyyyyyyy>;distinguishedName (hexadecimal) // It also handles the case when AD object does not have a SID, // Hence, <GUID=xxxxxxxx>;distinguishedName DWORD LwLdapParseExtendedDNResult( IN PCSTR pszExtDnResult, OUT PSTR* ppszSid ) { DWORD dwError = 0; PCSTR pszSidHex = NULL; PCSTR pszCurrExtDnResult = pszExtDnResult; DWORD dwSidLength = 0; PSTR pszSid = NULL; UCHAR* pucSIDByteArr = NULL; DWORD dwSIDByteCount = 0; PLW_SECURITY_IDENTIFIER pSID = NULL; LW_BAIL_ON_INVALID_STRING(pszCurrExtDnResult); if (strncasecmp(pszCurrExtDnResult, "<GUID=", sizeof("<GUID=")-1)) { dwError = LW_ERROR_LDAP_ERROR; LW_RTL_LOG_ERROR("Failed to find extended DN entry '%s' GUID part. [error code:%d]", pszExtDnResult, dwError); BAIL_ON_LW_ERROR(dwError); } while (*pszCurrExtDnResult != ';') { if (*pszCurrExtDnResult == '\0') { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LW_ERROR(dwError); } pszCurrExtDnResult++; } pszCurrExtDnResult++; if (strncasecmp(pszCurrExtDnResult, "<SID=", sizeof("<SID=")-1)) { LW_RTL_LOG_DEBUG("The extended DN entry '%s' has no SID part.", pszExtDnResult); goto cleanup; } pszSidHex = pszCurrExtDnResult + sizeof("<SID=") - 1; while (*(pszSidHex+dwSidLength) != '>') { if (*(pszSidHex+dwSidLength) == '\0') { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LW_ERROR(dwError); } ++dwSidLength; } if (*(pszSidHex+dwSidLength+1) != ';') { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LW_ERROR(dwError); } dwError = LwHexStrToByteArray( pszSidHex, &dwSidLength, &pucSIDByteArr, &dwSIDByteCount); BAIL_ON_LW_ERROR(dwError); dwError = LwAllocSecurityIdentifierFromBinary( pucSIDByteArr, dwSIDByteCount, &pSID); BAIL_ON_LW_ERROR(dwError); dwError = LwGetSecurityIdentifierString( pSID, &pszSid); BAIL_ON_LW_ERROR(dwError); cleanup: if (dwError) { LW_SAFE_FREE_STRING(pszSid); } *ppszSid = pszSid; LW_SAFE_FREE_MEMORY(pucSIDByteArr); if (pSID) { LwFreeSecurityIdentifier(pSID); } return dwError; error: // Do not actually handle any error here, // Do it in the cleanup, since there is a 'goto cleanup' goto cleanup; }
DWORD LwLdapPingTcp( PCSTR pszHostAddress, DWORD dwTimeoutSeconds ) { DWORD dwError = 0; int sysRet = 0; int fd = -1; struct in_addr addr; struct sockaddr_in socketAddress; struct timeval timeout; fd_set fds; int socketError; #ifdef GETSOCKNAME_TAKES_SOCKLEN_T socklen_t socketErrorLength = 0; #else int socketErrorLength = 0; #endif addr.s_addr = inet_addr(pszHostAddress); if (addr.s_addr == INADDR_NONE) { LW_RTL_LOG_ERROR("Could not convert address'%s' to in_addr", pszHostAddress); dwError = LW_ERROR_DNS_RESOLUTION_FAILED; BAIL_ON_LW_ERROR(dwError); } socketAddress.sin_family = AF_INET; socketAddress.sin_port = htons(389); socketAddress.sin_addr = addr; fd = socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { dwError = LwMapErrnoToLwError(errno); BAIL_ON_LW_ERROR(dwError); } sysRet = fcntl(fd, F_SETFL, O_NONBLOCK); if (sysRet < 0) { dwError = LwMapErrnoToLwError(errno); BAIL_ON_LW_ERROR(dwError); } sysRet = connect(fd, (struct sockaddr *)&socketAddress, sizeof(socketAddress)); { dwError = LwMapErrnoToLwError(errno); // We typically expect EINPROGRESS dwError = (LW_ERROR_ERRNO_EINPROGRESS == dwError) ? 0 : dwError; BAIL_ON_LW_ERROR(dwError); } FD_ZERO(&fds); FD_SET(fd, &fds); timeout.tv_sec = dwTimeoutSeconds; timeout.tv_usec = 0; sysRet = select(fd + 1, NULL, &fds, NULL, &timeout); if (sysRet < 0) { dwError = LwMapErrnoToLwError(errno); BAIL_ON_LW_ERROR(dwError); } switch (sysRet) { case 0: // We timed out LW_RTL_LOG_DEBUG("Timed out connecting to '%s'", pszHostAddress); // ISSUE-2008/09/16-dalmeida -- Technically, not a "domain"... dwError = LW_ERROR_DOMAIN_IS_OFFLINE; BAIL_ON_LW_ERROR(dwError); break; case 1: // Normal case break; default: // This should never happen. LW_RTL_LOG_DEBUG("Unexpected number of file descriptors returned (%d)", sysRet); dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LW_ERROR(dwError); break; } if (!FD_ISSET(fd, &fds)) { // ISSUE-2008/07/15-dalmeida -- Suitable error code? dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LW_ERROR(dwError); } socketError = 0; socketErrorLength = sizeof(socketError); sysRet = getsockopt(fd, SOL_SOCKET, SO_ERROR, &socketError, &socketErrorLength); if (sysRet < 0) { dwError = LwMapErrnoToLwError(errno); BAIL_ON_LW_ERROR(dwError); } if (socketErrorLength != sizeof(socketError)) { dwError = LW_ERROR_ERRNO_EMSGSIZE; BAIL_ON_LW_ERROR(dwError); } if (socketError) { dwError = LwMapErrnoToLwError(socketError); BAIL_ON_LW_ERROR(dwError); } error: if (fd != -1) { close(fd); } return dwError; }
DWORD LwMapErrnoToLwError( DWORD dwErrno ) { switch(dwErrno) { case 0: return LW_ERROR_SUCCESS; case EPERM: return ERROR_ACCESS_DENIED; case ENOENT: return ERROR_FILE_NOT_FOUND; case ESRCH: return LW_ERROR_NO_SUCH_PROCESS; case EINTR: return LW_ERROR_INTERRUPTED; case EIO: return LW_ERROR_GENERIC_IO; case ENXIO: return LW_ERROR_ERRNO_ENXIO; case E2BIG: return LW_ERROR_ERRNO_E2BIG; case ENOEXEC: return LW_ERROR_ERRNO_ENOEXEC; case EBADF: return LW_ERROR_INVALID_HANDLE; case ECHILD: return LW_ERROR_ERRNO_ECHILD; case EAGAIN: #if EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif return LW_ERROR_ERRNO_EAGAIN; case ENOMEM: return LW_ERROR_OUT_OF_MEMORY; case EACCES: return LW_ERROR_ACCESS_DENIED; case EFAULT: return LW_ERROR_ERRNO_EFAULT; case ENOTBLK: return LW_ERROR_ERRNO_ENOTBLK; case EBUSY: return LW_ERROR_ERRNO_EBUSY; case EEXIST: return LW_ERROR_ERRNO_EEXIST; case EXDEV: return LW_ERROR_ERRNO_EXDEV; case ENODEV: return LW_ERROR_ERRNO_ENODEV; case ENOTDIR: return LW_ERROR_ERRNO_ENOTDIR; case EISDIR: return LW_ERROR_ERRNO_EISDIR; case EINVAL: return LW_ERROR_INVALID_PARAMETER; case ENFILE: return LW_ERROR_ERRNO_ENFILE; case EMFILE: return LW_ERROR_ERRNO_EMFILE; case ENOTTY: return LW_ERROR_ERRNO_ENOTTY; case ETXTBSY: return LW_ERROR_ERRNO_ETXTBSY; case EFBIG: return LW_ERROR_ERRNO_EFBIG; case ENOSPC: return LW_ERROR_ERRNO_ENOSPC; case ESPIPE: return LW_ERROR_ERRNO_ESPIPE; case EROFS: return LW_ERROR_ERRNO_EROFS; case EMLINK: return LW_ERROR_ERRNO_EMLINK; case EPIPE: return LW_ERROR_ERRNO_EPIPE; case EDOM: return LW_ERROR_ERRNO_EDOM; case ERANGE: return LW_ERROR_ERRNO_ERANGE; #if defined(EDEADLOCK) && EDEADLOCK != EDEADLK case EDEADLOCK: #endif case EDEADLK: return LW_ERROR_ERRNO_EDEADLOCK; case ENAMETOOLONG: return LW_ERROR_ERRNO_ENAMETOOLONG; case ENOLCK: return LW_ERROR_ERRNO_ENOLCK; case ENOSYS: return LW_ERROR_NOT_SUPPORTED; #if ENOTEMPTY != EEXIST case ENOTEMPTY: return LW_ERROR_ERRNO_ENOTEMPTY; #endif case ELOOP: return LW_ERROR_ERRNO_ELOOP; case ENOMSG: return LW_ERROR_ERRNO_ENOMSG; case EIDRM: return LW_ERROR_ERRNO_EIDRM; #ifdef ECHRNG case ECHRNG: return LW_ERROR_ERRNO_ECHRNG; #endif #ifdef EL2NSYNC case EL2NSYNC: return LW_ERROR_ERRNO_EL2NSYNC; #endif #ifdef EL3HLT case EL3HLT: return LW_ERROR_ERRNO_EL3HLT; #endif #ifdef EL3RST case EL3RST: return LW_ERROR_ERRNO_EL3RST; #endif #ifdef ELNRNG case ELNRNG: return LW_ERROR_ERRNO_ELNRNG; #endif #ifdef EUNATCH case EUNATCH: return LW_ERROR_ERRNO_EUNATCH; #endif #ifdef ENOCSI case ENOCSI: return LW_ERROR_ERRNO_ENOCSI; #endif #ifdef EL2HLT case EL2HLT: return LW_ERROR_ERRNO_EL2HLT; #endif #ifdef EBADE case EBADE: return LW_ERROR_ERRNO_EBADE; #endif #ifdef EBADR case EBADR: return LW_ERROR_ERRNO_EBADR; #endif #ifdef EXFULL case EXFULL: return LW_ERROR_ERRNO_EXFULL; #endif #ifdef ENOANO case ENOANO: return LW_ERROR_ERRNO_ENOANO; #endif #ifdef EBADRQC case EBADRQC: return LW_ERROR_ERRNO_EBADRQC; #endif #ifdef EBADSLT case EBADSLT: return LW_ERROR_ERRNO_EBADSLT; #endif #ifdef EBFONT case EBFONT: return LW_ERROR_ERRNO_EBFONT; #endif #ifdef ENOSTR case ENOSTR: return LW_ERROR_ERRNO_ENOSTR; #endif #ifdef ENODATA case ENODATA: return LW_ERROR_ERRNO_ENODATA; #endif #ifdef ETIME case ETIME: return LW_ERROR_ERRNO_ETIME; #endif #ifdef ENOSR case ENOSR: return LW_ERROR_ERRNO_ENOSR; #endif #ifdef ENONET case ENONET: return LW_ERROR_ERRNO_ENONET; #endif #ifdef ENOPKG case ENOPKG: return LW_ERROR_ERRNO_ENOPKG; #endif case EREMOTE: return LW_ERROR_ERRNO_EREMOTE; case ENOLINK: return LW_ERROR_ERRNO_ENOLINK; #ifdef EADV case EADV: return LW_ERROR_ERRNO_EADV; #endif #ifdef ESRMNT case ESRMNT: return LW_ERROR_ERRNO_ESRMNT; #endif #ifdef ECOMM case ECOMM: return LW_ERROR_ERRNO_ECOMM; #endif case EPROTO: return LW_ERROR_ERRNO_EPROTO; case EMULTIHOP: return LW_ERROR_ERRNO_EMULTIHOP; #ifdef EDOTDOT case EDOTDOT: return LW_ERROR_ERRNO_EDOTDOT; #endif case EBADMSG: return LW_ERROR_ERRNO_EBADMSG; case EOVERFLOW: return LW_ERROR_ERRNO_EOVERFLOW; #ifdef ENOTUNIQ case ENOTUNIQ: return LW_ERROR_ERRNO_ENOTUNIQ; #endif #ifdef EBADFD case EBADFD: return LW_ERROR_ERRNO_EBADFD; #endif #ifdef EREMCHG case EREMCHG: return LW_ERROR_ERRNO_EREMCHG; #endif #ifdef ELIBACC case ELIBACC: return LW_ERROR_ERRNO_ELIBACC; #endif #ifdef ELIBBAD case ELIBBAD: return LW_ERROR_ERRNO_ELIBBAD; #endif #ifdef ELIBSCN case ELIBSCN: return LW_ERROR_ERRNO_ELIBSCN; #endif #ifdef ELIBMAX case ELIBMAX: return LW_ERROR_ERRNO_ELIBMAX; #endif #ifdef ELIBEXEC case ELIBEXEC: return LW_ERROR_ERRNO_ELIBEXEC; #endif case EILSEQ: return LW_ERROR_ERRNO_EILSEQ; #ifdef ERESTART case ERESTART: return LW_ERROR_ERRNO_ERESTART; #endif #ifdef ESTRPIPE case ESTRPIPE: return LW_ERROR_ERRNO_ESTRPIPE; #endif case EUSERS: return LW_ERROR_ERRNO_EUSERS; case ENOTSOCK: return LW_ERROR_ERRNO_ENOTSOCK; case EDESTADDRREQ: return LW_ERROR_ERRNO_EDESTADDRREQ; case EMSGSIZE: return LW_ERROR_ERRNO_EMSGSIZE; case EPROTOTYPE: return LW_ERROR_ERRNO_EPROTOTYPE; case ENOPROTOOPT: return LW_ERROR_ERRNO_ENOPROTOOPT; case EPROTONOSUPPORT: return LW_ERROR_ERRNO_EPROTONOSUPPORT; case ESOCKTNOSUPPORT: return LW_ERROR_ERRNO_ESOCKTNOSUPPORT; case EOPNOTSUPP: return LW_ERROR_ERRNO_EOPNOTSUPP; case EPFNOSUPPORT: return LW_ERROR_ERRNO_EPFNOSUPPORT; case EAFNOSUPPORT: return LW_ERROR_ERRNO_EAFNOSUPPORT; case EADDRINUSE: return LW_ERROR_ERRNO_EADDRINUSE; case EADDRNOTAVAIL: return LW_ERROR_ERRNO_EADDRNOTAVAIL; case ENETDOWN: return LW_ERROR_ERRNO_ENETDOWN; case ENETUNREACH: return LW_ERROR_ERRNO_ENETUNREACH; case ENETRESET: return LW_ERROR_ERRNO_ENETRESET; case ECONNABORTED: return LW_ERROR_ERRNO_ECONNABORTED; case ECONNRESET: return LW_ERROR_ERRNO_ECONNRESET; case ENOBUFS: return LW_ERROR_ERRNO_ENOBUFS; case EISCONN: return LW_ERROR_ERRNO_EISCONN; case ENOTCONN: return LW_ERROR_ERRNO_ENOTCONN; case ESHUTDOWN: return LW_ERROR_ERRNO_ESHUTDOWN; case ETOOMANYREFS: return LW_ERROR_ERRNO_ETOOMANYREFS; case ETIMEDOUT: return LW_ERROR_ERRNO_ETIMEDOUT; case ECONNREFUSED: return LW_ERROR_ERRNO_ECONNREFUSED; case EHOSTDOWN: return LW_ERROR_ERRNO_EHOSTDOWN; case EHOSTUNREACH: return LW_ERROR_ERRNO_EHOSTUNREACH; case EALREADY: return LW_ERROR_ERRNO_EALREADY; case EINPROGRESS: return LW_ERROR_ERRNO_EINPROGRESS; case ESTALE: return LW_ERROR_ERRNO_ESTALE; #ifdef EUCLEAN case EUCLEAN: return LW_ERROR_ERRNO_EUCLEAN; #endif #ifdef ENOTNAM case ENOTNAM: return LW_ERROR_ERRNO_ENOTNAM; #endif #ifdef ENAVAIL case ENAVAIL: return LW_ERROR_ERRNO_ENAVAIL; #endif #ifdef EISNAM case EISNAM: return LW_ERROR_ERRNO_EISNAM; #endif #ifdef EREMOTEIO case EREMOTEIO: return LW_ERROR_ERRNO_EREMOTEIO; #endif case EDQUOT: return LW_ERROR_ERRNO_EDQUOT; #ifdef ENOMEDIUM case ENOMEDIUM: return LW_ERROR_ERRNO_ENOMEDIUM; #endif #ifdef EMEDIUMTYPE case EMEDIUMTYPE: return LW_ERROR_ERRNO_EMEDIUMTYPE; #endif case ECANCELED: return LW_ERROR_ERRNO_ECANCELED; default: LW_RTL_LOG_ERROR("Unable to map errno %d", dwErrno); return LW_ERROR_UNKNOWN; } }
LW_NTSTATUS LwRtlSvcmLoadModule( LW_IN LW_PCWSTR pServiceName, LW_IN LW_PCWSTR pModulePath, LW_OUT PLW_SVCM_INSTANCE* ppInstance ) { NTSTATUS status = STATUS_SUCCESS; PLW_SVCM_INSTANCE pInstance = NULL; PSTR pModulePathA = NULL; LW_SVCM_MODULE_ENTRY_FUNCTION Entry = NULL; PSTR pEntryName = NULL; PSTR pBareName = NULL; PSTR pFinalSlash = NULL; PSTR pFinalDot = NULL; status = InitPool(); GCOS(status); status = LwRtlCStringAllocateFromWC16String(&pModulePathA, pModulePath); GCOS(status); pFinalSlash = strrchr(pModulePathA, '/'); pFinalDot = strrchr(pModulePathA, '.'); if (!pFinalSlash) { pFinalSlash = pModulePathA; } else { pFinalSlash++; } if (!pFinalDot) { pFinalDot = pModulePathA + strlen(pModulePathA); } status = LW_RTL_ALLOCATE(&pBareName, CHAR, (pFinalDot - pFinalSlash) + 1); GCOS(status); memcpy(pBareName, pFinalSlash, pFinalDot - pFinalSlash); status = LwRtlCStringAllocatePrintf(&pEntryName, "_LwSvcmEntry_%s", pBareName); GCOS(status); status = LW_RTL_ALLOCATE_AUTO(&pInstance); GCOS(status); LW_RTL_LOG_DEBUG("Loading service module: %s", pModulePathA); (void) dlerror(); pInstance->pDlHandle = dlopen(pModulePathA, RTLD_LOCAL | RTLD_NOW); if (!pInstance->pDlHandle) { LW_RTL_LOG_ERROR( "Could not load service module '%s': %s", pModulePathA, dlerror()); status = LwErrnoToNtStatus(errno); GCOS(status); } (void) dlerror(); Entry = dlsym(pInstance->pDlHandle, pEntryName); if (!Entry) { LW_RTL_LOG_ERROR( "Could not load entry point from service module '%s': %s", pModulePathA, dlerror()); status = LwErrnoToNtStatus(errno); if (!status) { status = STATUS_BAD_DLL_ENTRYPOINT; } GCOS(status); } status = LwRtlSvcmInitializeInstance(pInstance, pServiceName, pModulePathA, Entry); GCOS(status); cleanup: RTL_FREE(&pModulePathA); RTL_FREE(&pBareName); RTL_FREE(&pEntryName); if (!NT_SUCCESS(status)) { LwRtlSvcmUnload(pInstance); pInstance = NULL; } *ppInstance = pInstance; return status; }
DWORD LwMapLdapErrorToLwError( DWORD dwErr ) { switch(dwErr) { case LDAP_SUCCESS: return LW_ERROR_SUCCESS; case LDAP_SERVER_DOWN: return LW_ERROR_LDAP_SERVER_DOWN; case LDAP_LOCAL_ERROR: return LW_ERROR_LDAP_LOCAL_ERROR; case LDAP_ENCODING_ERROR: return LW_ERROR_LDAP_ENCODING_ERROR; case LDAP_DECODING_ERROR: return LW_ERROR_LDAP_DECODING_ERROR; case LDAP_TIMEOUT: return LW_ERROR_LDAP_TIMEOUT; case LDAP_AUTH_UNKNOWN: return LW_ERROR_LDAP_AUTH_UNKNOWN; case LDAP_FILTER_ERROR: return LW_ERROR_LDAP_FILTER_ERROR; case LDAP_USER_CANCELLED: return LW_ERROR_LDAP_USER_CANCELLED; case LDAP_PARAM_ERROR: return LW_ERROR_LDAP_PARAM_ERROR; case LDAP_NO_MEMORY: return LW_ERROR_LDAP_NO_MEMORY; case LDAP_CONNECT_ERROR: return LW_ERROR_LDAP_CONNECT_ERROR; case LDAP_NOT_SUPPORTED: return LW_ERROR_LDAP_NOT_SUPPORTED; case LDAP_CONTROL_NOT_FOUND: return LW_ERROR_LDAP_CONTROL_NOT_FOUND; case LDAP_NO_RESULTS_RETURNED: return LW_ERROR_LDAP_NO_RESULTS_RETURNED; case LDAP_MORE_RESULTS_TO_RETURN: return LW_ERROR_LDAP_MORE_RESULTS_TO_RETURN; case LDAP_CLIENT_LOOP: return LW_ERROR_LDAP_CLIENT_LOOP; case LDAP_REFERRAL_LIMIT_EXCEEDED: return LW_ERROR_LDAP_REFERRAL_LIMIT_EXCEEDED; case LDAP_OPERATIONS_ERROR: return LW_ERROR_LDAP_OPERATIONS_ERROR; case LDAP_PROTOCOL_ERROR: return LW_ERROR_LDAP_PROTOCOL_ERROR; case LDAP_TIMELIMIT_EXCEEDED: return LW_ERROR_LDAP_TIMELIMIT_EXCEEDED; case LDAP_SIZELIMIT_EXCEEDED: return LW_ERROR_LDAP_SIZELIMIT_EXCEEDED; case LDAP_COMPARE_FALSE: return LW_ERROR_LDAP_COMPARE_FALSE; case LDAP_COMPARE_TRUE: return LW_ERROR_LDAP_COMPARE_TRUE; case LDAP_STRONG_AUTH_NOT_SUPPORTED: return LW_ERROR_LDAP_STRONG_AUTH_NOT_SUPPORTED; case LDAP_STRONG_AUTH_REQUIRED: return LW_ERROR_LDAP_STRONG_AUTH_REQUIRED; case LDAP_PARTIAL_RESULTS: return LW_ERROR_LDAP_PARTIAL_RESULTS; case LDAP_NO_SUCH_ATTRIBUTE: return LW_ERROR_LDAP_NO_SUCH_ATTRIBUTE; case LDAP_UNDEFINED_TYPE: return LW_ERROR_LDAP_UNDEFINED_TYPE; case LDAP_INAPPROPRIATE_MATCHING: return LW_ERROR_LDAP_INAPPROPRIATE_MATCHING; case LDAP_CONSTRAINT_VIOLATION: return LW_ERROR_LDAP_CONSTRAINT_VIOLATION; case LDAP_TYPE_OR_VALUE_EXISTS: return LW_ERROR_LDAP_TYPE_OR_VALUE_EXISTS; case LDAP_INVALID_SYNTAX: return LW_ERROR_LDAP_INVALID_SYNTAX; case LDAP_NO_SUCH_OBJECT: return LW_ERROR_LDAP_NO_SUCH_OBJECT; case LDAP_ALIAS_PROBLEM: return LW_ERROR_LDAP_ALIAS_PROBLEM; case LDAP_INVALID_DN_SYNTAX: return LW_ERROR_LDAP_INVALID_DN_SYNTAX; case LDAP_IS_LEAF: return LW_ERROR_LDAP_IS_LEAF; case LDAP_ALIAS_DEREF_PROBLEM: return LW_ERROR_LDAP_ALIAS_DEREF_PROBLEM; case LDAP_REFERRAL: return LW_ERROR_LDAP_REFERRAL; case LDAP_ADMINLIMIT_EXCEEDED: return LW_ERROR_LDAP_ADMINLIMIT_EXCEEDED; case LDAP_UNAVAILABLE_CRITICAL_EXTENSION: return LW_ERROR_LDAP_UNAVAILABLE_CRITICAL_EXTENSION; case LDAP_CONFIDENTIALITY_REQUIRED: return LW_ERROR_LDAP_CONFIDENTIALITY_REQUIRED; case LDAP_SASL_BIND_IN_PROGRESS: return LW_ERROR_LDAP_SASL_BIND_IN_PROGRESS; case LDAP_X_PROXY_AUTHZ_FAILURE: return LW_ERROR_LDAP_X_PROXY_AUTHZ_FAILURE; case LDAP_INAPPROPRIATE_AUTH: return LW_ERROR_LDAP_INAPPROPRIATE_AUTH; case LDAP_INVALID_CREDENTIALS: return LW_ERROR_LDAP_INVALID_CREDENTIALS; case LDAP_INSUFFICIENT_ACCESS: return LW_ERROR_LDAP_INSUFFICIENT_ACCESS; case LDAP_BUSY: return LW_ERROR_LDAP_BUSY; case LDAP_UNAVAILABLE: return LW_ERROR_LDAP_UNAVAILABLE; case LDAP_UNWILLING_TO_PERFORM: return LW_ERROR_LDAP_UNWILLING_TO_PERFORM; case LDAP_LOOP_DETECT: return LW_ERROR_LDAP_LOOP_DETECT; case LDAP_NAMING_VIOLATION: return LW_ERROR_LDAP_NAMING_VIOLATION; case LDAP_OBJECT_CLASS_VIOLATION: return LW_ERROR_LDAP_OBJECT_CLASS_VIOLATION; case LDAP_NOT_ALLOWED_ON_NONLEAF: return LW_ERROR_LDAP_NOT_ALLOWED_ON_NONLEAF; case LDAP_NOT_ALLOWED_ON_RDN: return LW_ERROR_LDAP_NOT_ALLOWED_ON_RDN; case LDAP_ALREADY_EXISTS: return LW_ERROR_LDAP_ALREADY_EXISTS; case LDAP_NO_OBJECT_CLASS_MODS: return LW_ERROR_LDAP_NO_OBJECT_CLASS_MODS; case LDAP_RESULTS_TOO_LARGE: return LW_ERROR_LDAP_RESULTS_TOO_LARGE; case LDAP_AFFECTS_MULTIPLE_DSAS: return LW_ERROR_LDAP_AFFECTS_MULTIPLE_DSAS; case LDAP_CUP_RESOURCES_EXHAUSTED: return LW_ERROR_LDAP_CUP_RESOURCES_EXHAUSTED; case LDAP_CUP_SECURITY_VIOLATION: return LW_ERROR_LDAP_CUP_SECURITY_VIOLATION; case LDAP_CUP_INVALID_DATA: return LW_ERROR_LDAP_CUP_INVALID_DATA; case LDAP_CUP_UNSUPPORTED_SCHEME: return LW_ERROR_LDAP_CUP_UNSUPPORTED_SCHEME; case LDAP_CUP_RELOAD_REQUIRED: return LW_ERROR_LDAP_CUP_RELOAD_REQUIRED; case LDAP_CANCELLED: return LW_ERROR_LDAP_CANCELLED; case LDAP_NO_SUCH_OPERATION: return LW_ERROR_LDAP_NO_SUCH_OPERATION; case LDAP_TOO_LATE: return LW_ERROR_LDAP_TOO_LATE; case LDAP_CANNOT_CANCEL: return LW_ERROR_LDAP_CANNOT_CANCEL; case LDAP_ASSERTION_FAILED: return LW_ERROR_LDAP_ASSERTION_FAILED; default: LW_RTL_LOG_ERROR("Unable to map ldap error %d", dwErr); return LW_ERROR_UNKNOWN; } }
DWORD LwLdapOpenDirectoryServerSingleAttempt( IN PCSTR pszServerAddress, IN PCSTR pszServerName, IN DWORD dwTimeoutSec, IN DWORD dwFlags, OUT PLW_LDAP_DIRECTORY_CONTEXT* ppDirectory ) { DWORD dwError = LW_ERROR_SUCCESS; LDAP * ld = NULL; PLW_LDAP_DIRECTORY_CONTEXT pDirectory = NULL; int rc = LDAP_VERSION3; DWORD dwPort = 389; struct timeval timeout = {0}; BOOLEAN bLdapSeal = FALSE; timeout.tv_sec = dwTimeoutSec; LW_BAIL_ON_INVALID_STRING(pszServerName); LW_BAIL_ON_INVALID_STRING(pszServerAddress); if (dwFlags & LW_LDAP_OPT_GLOBAL_CATALOG) { dwPort = 3268; } // This creates the ld without immediately connecting to the server. // That way a connection timeout can be set first. ld = (LDAP *)ldap_init(pszServerAddress, dwPort); if (!ld) { dwError = LwMapErrnoToLwError(errno); LW_RTL_LOG_ERROR("Failed to open LDAP connection to domain controller"); BAIL_ON_LW_ERROR(dwError); LW_RTL_LOG_ERROR("Failed to get errno for failed open LDAP connection"); dwError = LW_ERROR_LDAP_ERROR; BAIL_ON_LW_ERROR(dwError); } dwError = ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &timeout); BAIL_ON_LDAP_ERROR(dwError); dwError = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &rc); if (dwError) { LW_RTL_LOG_ERROR("Failed to set LDAP option protocol version"); BAIL_ON_LDAP_ERROR(dwError); } dwError = ldap_set_option( ld, LDAP_OPT_REFERRALS, (void *)LDAP_OPT_OFF); if (dwError) { LW_RTL_LOG_ERROR("Failed to set LDAP option to not follow referrals"); BAIL_ON_LDAP_ERROR(dwError); } /* This tells ldap to retry when select returns with EINTR */ dwError = ldap_set_option( ld, LDAP_OPT_RESTART, (void *)LDAP_OPT_ON); if (dwError) { LW_RTL_LOG_ERROR("Failed to set LDAP option to auto retry "); BAIL_ON_LDAP_ERROR(dwError); } if (dwFlags & LW_LDAP_OPT_SIGN_AND_SEAL) { bLdapSeal = TRUE; } dwError = LwAllocateMemory(sizeof(*pDirectory), OUT_PPVOID(&pDirectory)); BAIL_ON_LW_ERROR(dwError); pDirectory->ld = ld; ld = NULL; if (dwFlags & LW_LDAP_OPT_ANNONYMOUS) { dwError = LwLdapBindDirectoryAnonymous((HANDLE)pDirectory); } else { dwError = LwLdapBindDirectory( (HANDLE)pDirectory, pszServerName, bLdapSeal); } // The above functions return -1 when a connection times out. if (dwError == (DWORD)-1) { dwError = ETIMEDOUT; } BAIL_ON_LW_ERROR(dwError); *ppDirectory = pDirectory; cleanup: return(dwError); error: if (pDirectory) { LwLdapCloseDirectory(pDirectory); } if (ld) { ldap_unbind_s(ld); } *ppDirectory = (HANDLE)NULL; goto cleanup; }
DWORD LwLdapDirectorySearch( HANDLE hDirectory, PCSTR pszObjectDN, int scope, PCSTR pszQuery, PSTR* ppszAttributeList, LDAPMessage** ppMessage ) { DWORD dwError = LW_ERROR_SUCCESS; PLW_LDAP_DIRECTORY_CONTEXT pDirectory = (PLW_LDAP_DIRECTORY_CONTEXT)hDirectory; struct timeval timeout = {0}; LDAPMessage* pMessage = NULL; timeout.tv_sec = 15; timeout.tv_usec = 0; dwError = ldap_search_st(pDirectory->ld, pszObjectDN, scope, pszQuery, ppszAttributeList, 0, &timeout, &pMessage); if (dwError) { if (dwError == LDAP_NO_SUCH_OBJECT) { LW_RTL_LOG_VERBOSE("Caught LDAP_NO_SUCH_OBJECT Error on ldap search"); BAIL_ON_LDAP_ERROR(dwError); } if (dwError == LDAP_REFERRAL) { LW_RTL_LOG_ERROR("Caught LDAP_REFERRAL Error on ldap search"); LW_RTL_LOG_ERROR("LDAP Search Info: DN: [%s]", LW_IS_NULL_OR_EMPTY_STR(pszObjectDN) ? "<null>" : pszObjectDN); LW_RTL_LOG_ERROR("LDAP Search Info: scope: [%d]", scope); LW_RTL_LOG_ERROR("LDAP Search Info: query: [%s]", LW_IS_NULL_OR_EMPTY_STR(pszQuery) ? "<null>" : pszQuery); if (ppszAttributeList) { size_t i; for (i = 0; ppszAttributeList[i] != NULL; i++) { LW_RTL_LOG_ERROR("LDAP Search Info: attribute: [%s]", ppszAttributeList[i]); } } else { LW_RTL_LOG_ERROR("Error: LDAP Search Info: no attributes were specified"); } } BAIL_ON_LDAP_ERROR(dwError); } *ppMessage = pMessage; cleanup: return(dwError); error: *ppMessage = NULL; if (pMessage) { ldap_msgfree(pMessage); } goto cleanup; }
DWORD SynchronizePassword( PCSTR pSmbdPath ) { DWORD error = 0; PSTR pSecretsPath = NULL; LW_HANDLE hLsa = NULL; PLSA_MACHINE_PASSWORD_INFO_A pPasswordInfo = NULL; PLSA_PSTORE_PLUGIN_DISPATCH pDispatch = NULL; PLSA_PSTORE_PLUGIN_CONTEXT pContext = NULL; HANDLE hReg = NULL; error = LwRegOpenServer(&hReg); BAIL_ON_LSA_ERROR(error); error = GetSecretsPath( pSmbdPath, &pSecretsPath); BAIL_ON_LSA_ERROR(error); error = RegUtilAddKey( hReg, LSA_PSTORE_REG_ROOT_KEY_PATH, NULL, LSA_PSTORE_REG_ROOT_KEY_RELATIVE_PATH_PLUGINS "\\" PLUGIN_NAME); BAIL_ON_LSA_ERROR(error); error = RegUtilSetValue( hReg, LSA_PSTORE_REG_ROOT_KEY_PATH, NULL, LSA_PSTORE_REG_ROOT_KEY_RELATIVE_PATH_PLUGINS "\\" PLUGIN_NAME, "SecretsPath", REG_SZ, pSecretsPath, strlen(pSecretsPath)); BAIL_ON_LSA_ERROR(error); error = RegUtilSetValue( hReg, HKEY_THIS_MACHINE, NULL, LSA_PSTORE_REG_ROOT_KEY_RELATIVE_PATH_PLUGINS "\\" PLUGIN_NAME, "Path", REG_SZ, PLUGIN_PATH, strlen(PLUGIN_PATH)); BAIL_ON_LSA_ERROR(error); error = AddSambaLoadPath(hReg); BAIL_ON_LSA_ERROR(error); error = LsaOpenServer( &hLsa); if (error) { LW_RTL_LOG_ERROR("Unable to contact lsassd"); } BAIL_ON_LSA_ERROR(error); error = LsaAdGetMachinePasswordInfo( hLsa, NULL, &pPasswordInfo); if (error == NERR_SetupNotJoined) { LW_RTL_LOG_ERROR("Unable to write machine password in secrets.tdb because PowerBroker Identity Services is not joined. The password will be written to secrets.tdb on the next successful join attempt"); error = 0; } else { BAIL_ON_LSA_ERROR(error); error = LsaPstorePluginInitializeContext( LSA_PSTORE_PLUGIN_VERSION, PLUGIN_NAME, &pDispatch, &pContext); BAIL_ON_LSA_ERROR(error); error = pDispatch->SetPasswordInfoA( pContext, pPasswordInfo); BAIL_ON_LSA_ERROR(error); } cleanup: LW_SAFE_FREE_STRING(pSecretsPath); if (hLsa != NULL) { LsaCloseServer(hLsa); } if (hReg != NULL) { LwRegCloseServer(hReg); } if (pPasswordInfo != NULL) { LsaAdFreeMachinePasswordInfo(pPasswordInfo); } if (pContext) { pDispatch->Cleanup(pContext); } return error; }
static DWORD LwGssGetSingleErrorMessage( OUT PSTR* ppszErrorMessage, IN OM_uint32 Status, IN BOOLEAN IsMajor ) { DWORD dwError = 0; PSTR pszErrorMessage = NULL; OM_uint32 majorStatus = 0; OM_uint32 minorStatus = 0; gss_buffer_desc message = GSS_C_EMPTY_BUFFER; OM_uint32 messageContext = 0; int statusType = IsMajor ? GSS_C_GSS_CODE : GSS_C_MECH_CODE; do { majorStatus = gss_display_status( &minorStatus, Status, statusType, GSS_C_NULL_OID, &messageContext, &message); if (majorStatus != GSS_S_COMPLETE) { LW_RTL_LOG_ERROR("Call to gss_display_status() failed with " "majorStatus = 0x%08x, minorStatus = 0x%08x", majorStatus, minorStatus); dwError = ERROR_INTERNAL_ERROR; BAIL_ON_LW_ERROR(dwError); } if (!pszErrorMessage) { dwError = LwAllocateString((PSTR)message.value, &pszErrorMessage); BAIL_ON_LW_ERROR(dwError); } else { PSTR pszNewErrorMessage = NULL; dwError = LwAllocateStringPrintf(&pszNewErrorMessage, "%s; %s", pszErrorMessage, (PSTR)message.value); BAIL_ON_LW_ERROR(dwError); LW_SAFE_FREE_STRING(pszErrorMessage); pszErrorMessage = pszNewErrorMessage; } majorStatus = gss_release_buffer(&minorStatus, &message); } while (messageContext); error: if (dwError) { LW_SAFE_FREE_STRING(pszErrorMessage); } if (message.value) { majorStatus = gss_release_buffer(&minorStatus, &message); } *ppszErrorMessage = pszErrorMessage; return dwError; }
DWORD GetSecretsPath( PCSTR pSmbdPath, PSTR* ppPath ) { DWORD error = 0; PSTR pCommandLine = NULL; PCSTR ppArgs[] = { "/bin/sh", "-c", NULL, NULL }; PSTR pSambaPrivateDir = NULL; PSTR pPath = NULL; struct stat statBuf = { 0 }; // Look for secrets.tdb in the statedir (Ubuntu 10.10 is like this) error = LwAllocateStringPrintf( &pCommandLine, "%s -b | grep STATEDIR:", pSmbdPath ); BAIL_ON_LSA_ERROR(error); ppArgs[2] = pCommandLine; error = CaptureOutputWithStderr( "/bin/sh", ppArgs, &pSambaPrivateDir, NULL); if (error == ERROR_BAD_COMMAND) { pSambaPrivateDir = NULL; error = ERROR_BAD_COMMAND; } else { if (strstr(pSambaPrivateDir, ": ")) { char *pValueStart = strstr(pSambaPrivateDir, ": ") + 2; memmove( pSambaPrivateDir, pValueStart, strlen(pSambaPrivateDir) - (pValueStart - pSambaPrivateDir) + 1); } LwStripWhitespace( pSambaPrivateDir, TRUE, TRUE); error = LwAllocateStringPrintf( &pPath, "%s/secrets.tdb", pSambaPrivateDir ); BAIL_ON_LSA_ERROR(error); // Verify the path exists if (stat(pPath, &statBuf) < 0) { if (errno == ENOENT) { // Try the private dir instead LW_SAFE_FREE_STRING(pSambaPrivateDir); LW_SAFE_FREE_STRING(pPath); } else { LW_RTL_LOG_ERROR("Cannot find secrets.tdb at %s", pPath); error = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(error); } } } if (pPath == NULL) { // This version of smbd is older than 3.5, or the distro vendor decided // to put the file in the private dir (Fedora 14 is like that). LW_SAFE_FREE_STRING(pCommandLine); error = LwAllocateStringPrintf( &pCommandLine, "%s -b | grep PRIVATE_DIR:", pSmbdPath ); BAIL_ON_LSA_ERROR(error); ppArgs[2] = pCommandLine; error = CaptureOutputWithStderr( "/bin/sh", ppArgs, &pSambaPrivateDir, NULL); BAIL_ON_LSA_ERROR(error); LwStripWhitespace( pSambaPrivateDir, TRUE, TRUE); if (strstr(pSambaPrivateDir, ": ")) { char *pValueStart = strstr(pSambaPrivateDir, ": ") + 2; memmove( pSambaPrivateDir, pValueStart, strlen(pSambaPrivateDir) - (pValueStart - pSambaPrivateDir) + 1); } error = LwAllocateStringPrintf( &pPath, "%s/secrets.tdb", pSambaPrivateDir ); BAIL_ON_LSA_ERROR(error); } cleanup: *ppPath = pPath; LW_SAFE_FREE_STRING(pCommandLine); LW_SAFE_FREE_STRING(pSambaPrivateDir); return error; }
static DWORD LsaPstorepCallPlugin( IN PCSTR Operation, IN LSA_PSTORE_CALL_PLUGIN_CALLBACK Callback, IN PLSA_PSTORE_CALL_PLUGIN_ARGS Arguments ) { DWORD dwError = 0; int EE = 0; LSA_PSTORE_PLUGIN_INFO pluginInfo = { 0 }; PSTR* pluginNames = 0; DWORD pluginCount = 0; DWORD i = 0; PCSTR method = NULL; dwError = LsaPstorepGetPluginNames(&pluginNames, &pluginCount); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); for (i = 0; i < pluginCount; i++) { LsaPstorepCleanupPlugin(&pluginInfo); dwError = LsaPstorepInitializePlugin(&pluginInfo, pluginNames[i]); if (dwError) { LW_RTL_LOG_ERROR("Failed to load plugin %s with error = %u (%s)", pluginNames[i], dwError, LW_RTL_LOG_SAFE_STRING(LwWin32ExtErrorToName(dwError))); dwError = 0; continue; } dwError = Callback( pluginInfo.Name, pluginInfo.Dispatch, pluginInfo.Context, Arguments, &method); if (dwError) { if (method) { LW_RTL_LOG_ERROR( "Failed %s operation on plugin %s " "while calling %s method with error = %u (%s)", LW_RTL_LOG_SAFE_STRING(Operation), pluginNames[i], method, dwError, LW_RTL_LOG_SAFE_STRING(LwWin32ExtErrorToName(dwError))); } else { LW_RTL_LOG_ERROR( "Failed %s operation on plugin %s " "with error = %u (%s)", LW_RTL_LOG_SAFE_STRING(Operation), pluginNames[i], dwError, LW_RTL_LOG_SAFE_STRING(LwWin32ExtErrorToName(dwError))); } dwError = 0; continue; } } cleanup: LsaPstorepCleanupPlugin(&pluginInfo); LSA_PSTORE_FREE_STRING_ARRAY_A(&pluginNames, &pluginCount); LSA_PSTORE_LOG_LEAVE_ERROR_EE(dwError, EE); return dwError; }
int main( int argc, char *argv[] ) { enum { UNSET, SHOW_HELP, CHECK_VERSION, INSTALL, UNINSTALL } mode = UNSET; PCSTR pSmbdPath = NULL; PSTR pFoundSmbdPath = NULL; DWORD error = 0; DWORD argIndex = 0; LW_RTL_LOG_LEVEL logLevel = LW_RTL_LOG_LEVEL_ERROR; PCSTR pErrorSymbol = NULL; PSTR pVersion = NULL; BOOLEAN smbdExists = FALSE; BOOLEAN force = FALSE; for (argIndex = 1; argIndex < argc; argIndex++) { if (!strcmp(argv[argIndex], "--check-version")) { if (mode == UNSET) { mode = CHECK_VERSION; } else { mode = SHOW_HELP; } } else if (!strcmp(argv[argIndex], "--install")) { if (mode == UNSET) { mode = INSTALL; } else { mode = SHOW_HELP; } } else if (!strcmp(argv[argIndex], "--uninstall")) { if (mode == UNSET) { mode = UNINSTALL; } else { mode = SHOW_HELP; } } else if (!strcmp(argv[argIndex], "--force")) { if (mode == INSTALL || mode== UNINSTALL) { force = TRUE; } else { mode = SHOW_HELP; } } else if (!strcmp(argv[argIndex], "--loglevel")) { argIndex++; if (argIndex >= argc) { error = ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(error); } if (!strcmp(argv[argIndex], "error")) { logLevel = LW_RTL_LOG_LEVEL_ERROR; } else if (!strcmp(argv[argIndex], "warning")) { logLevel = LW_RTL_LOG_LEVEL_WARNING; } else if (!strcmp(argv[argIndex], "info")) { logLevel = LW_RTL_LOG_LEVEL_INFO; } else if (!strcmp(argv[argIndex], "verbose")) { logLevel = LW_RTL_LOG_LEVEL_VERBOSE; } else if (!strcmp(argv[argIndex], "debug")) { logLevel = LW_RTL_LOG_LEVEL_DEBUG; } else { error = ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(error); } } else if (argIndex == argc - 1) { pSmbdPath = argv[argIndex]; } else { mode = SHOW_HELP; } } if (mode == UNSET || mode == SHOW_HELP) { ShowUsage(argv[0]); goto cleanup; } LwRtlLogSetCallback(LogCallback, NULL); LwRtlLogSetLevel(logLevel); if (pSmbdPath == NULL) { PCSTR pSearchPath = "/usr/sbin:/usr/local/sbin:/usr/local/samba/sbin:/opt/csw/samba/sbin:/opt/sfw/samba/sbin:/opt/csw/bin:/usr/local/bin"; error = FindFileInPath( "smbd", pSearchPath, &pFoundSmbdPath); if (error == ERROR_FILE_NOT_FOUND) { LW_RTL_LOG_ERROR("The smbd file could not be automatically found on your system. The search path was '%s'. Pass the correct location as the last argument to this program.", pSearchPath); } BAIL_ON_LSA_ERROR(error); pSmbdPath = pFoundSmbdPath; } error = LwCheckFileTypeExists( pSmbdPath, LWFILE_REGULAR, &smbdExists); BAIL_ON_LSA_ERROR(error); if (!smbdExists) { error = LwCheckFileTypeExists( pSmbdPath, LWFILE_SYMLINK, &smbdExists); BAIL_ON_LSA_ERROR(error); } if (!smbdExists) { LW_RTL_LOG_ERROR("Smbd file not found at path '%s'", pSmbdPath); } error = CheckSambaVersion(pSmbdPath, &pVersion); if (force == FALSE) { BAIL_ON_LSA_ERROR(error); } if (mode == CHECK_VERSION) { fprintf(stderr, "Samba version supported\n"); } else if (mode == INSTALL) { if (geteuid() != 0) { fprintf(stderr, "Please use the root account to install the Samba interop libraries\n"); goto cleanup; } error = InstallWbclient(pSmbdPath); BAIL_ON_LSA_ERROR(error); if (pVersion && strncmp(pVersion, "3.0.", sizeof("3.0.") - 1) == 0) { // Only Samba 3.0.x needs this error = InstallLwiCompat(pSmbdPath); BAIL_ON_LSA_ERROR(error); } error = SynchronizePassword( pSmbdPath); BAIL_ON_LSA_ERROR(error); fprintf(stderr, "Install successful\n"); } else if (mode == UNINSTALL) { if (geteuid() != 0) { fprintf(stderr, "Please use the root account to uninstall the Samba interop libraries\n"); goto cleanup; } error = UninstallWbclient(pSmbdPath); BAIL_ON_LSA_ERROR(error); error = UninstallLwiCompat(pSmbdPath); BAIL_ON_LSA_ERROR(error); error = DeletePassword( pSmbdPath); BAIL_ON_LSA_ERROR(error); fprintf(stderr, "Uninstall successful\n"); } else { fprintf(stderr, "Uninstall mode not implemented\n"); error = ERROR_INVALID_PARAMETER; BAIL_ON_LSA_ERROR(error); } cleanup: LW_SAFE_FREE_STRING(pFoundSmbdPath); LW_SAFE_FREE_STRING(pVersion); if (error) { pErrorSymbol = LwWin32ErrorToName(error); if (pErrorSymbol != NULL) { fprintf(stderr, "Error: %s\n", pErrorSymbol); } else { fprintf(stderr, "Unknown error\n"); } } return error; }
DWORD DeletePassword( PCSTR pSmbdPath ) { DWORD error = 0; PLSA_PSTORE_PLUGIN_DISPATCH pDispatch = NULL; PLSA_PSTORE_PLUGIN_CONTEXT pContext = NULL; PSTR pSecretsPath = NULL; LW_HANDLE hLsa = NULL; PLSA_MACHINE_ACCOUNT_INFO_A pAccountInfo = NULL; HANDLE hReg = NULL; error = LwRegOpenServer(&hReg); BAIL_ON_LSA_ERROR(error); // Even though this was set during the install process, we'll try setting // it again. This way if the user calls uninstall without calling install // first, they won't get an error. error = GetSecretsPath( pSmbdPath, &pSecretsPath); BAIL_ON_LSA_ERROR(error); error = LsaOpenServer( &hLsa); if (error) { LW_RTL_LOG_ERROR("Unable to contact lsassd"); } BAIL_ON_LSA_ERROR(error); error = LsaAdGetMachineAccountInfo( hLsa, NULL, &pAccountInfo); BAIL_ON_LSA_ERROR(error); error = RegUtilAddKey( hReg, LSA_PSTORE_REG_ROOT_KEY_PATH, NULL, LSA_PSTORE_REG_ROOT_KEY_RELATIVE_PATH_PLUGINS "\\" PLUGIN_NAME); BAIL_ON_LSA_ERROR(error); error = RegUtilSetValue( hReg, LSA_PSTORE_REG_ROOT_KEY_PATH, NULL, LSA_PSTORE_REG_ROOT_KEY_RELATIVE_PATH_PLUGINS "\\" PLUGIN_NAME, "SecretsPath", REG_SZ, pSecretsPath, strlen(pSecretsPath)); BAIL_ON_LSA_ERROR(error); error = RemoveSambaLoadPath(hReg); BAIL_ON_LSA_ERROR(error); error = LsaPstorePluginInitializeContext( LSA_PSTORE_PLUGIN_VERSION, PLUGIN_NAME, &pDispatch, &pContext); BAIL_ON_LSA_ERROR(error); error = pDispatch->DeletePasswordInfoA( pContext, pAccountInfo); BAIL_ON_LSA_ERROR(error); cleanup: if (pContext) { pDispatch->Cleanup(pContext); } if (hReg != NULL) { LwRegCloseServer(hReg); } if (hLsa != NULL) { LsaCloseServer(hLsa); } if (pAccountInfo != NULL) { LsaAdFreeMachineAccountInfo(pAccountInfo); } return error; }
static DWORD LsaPstorepGetPluginPath( IN PCSTR pszName, OUT PSTR* ppszPath ) { DWORD dwError = 0; int EE = 0; HANDLE registryConnection = NULL; HKEY keyHandle = NULL; PSTR pszKeyPath = NULL; PSTR pszPath = NULL; dwError = LwNtStatusToWin32Error(LwRtlCStringAllocatePrintf( &pszKeyPath, "%s\\%s", LSA_PSTORE_REG_KEY_PATH_PLUGINS, pszName)); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); dwError = LwRegOpenServer(®istryConnection); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); dwError = LwRegOpenKeyExA( registryConnection, NULL, pszKeyPath, 0, GENERIC_READ, &keyHandle); if (dwError == LWREG_ERROR_NO_SUCH_KEY_OR_VALUE) { LW_RTL_LOG_ERROR("LSA pstore plugin '%s' is missing its configuration registry key '%s'", pszName, pszKeyPath); dwError = ERROR_DLL_INIT_FAILED; GOTO_CLEANUP_EE(EE); } GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); dwError = LsaPstorepRegGetStringA( registryConnection, keyHandle, LSA_PSTORE_REG_VALUE_NAME_PLUGINS_PATH, &pszPath); if (dwError == LWREG_ERROR_NO_SUCH_KEY_OR_VALUE) { LW_RTL_LOG_ERROR("LSA pstore plugin '%s' is missing the '%s' configuration value from its configuration registry key '%s'", pszName, LSA_PSTORE_REG_VALUE_NAME_PLUGINS_PATH, pszKeyPath); dwError = ERROR_DLL_INIT_FAILED; GOTO_CLEANUP_EE(EE); } GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); cleanup: if (dwError) { LSA_PSTORE_FREE(&pszPath); } if (keyHandle) { LwRegCloseKey(registryConnection, keyHandle); } if (registryConnection) { LwRegCloseServer(registryConnection); } LSA_PSTORE_FREE(&pszKeyPath); *ppszPath = pszPath; LSA_PSTORE_LOG_LEAVE_ERROR_EE(dwError, EE); return dwError; }
DWORD LwLdapOpenDirectoryServer( IN PCSTR pszServerAddress, IN PCSTR pszServerName, IN DWORD dwFlags, OUT PHANDLE phDirectory ) { DWORD dwError = LW_ERROR_SUCCESS; PLW_LDAP_DIRECTORY_CONTEXT pDirectory = NULL; DWORD dwAttempt = 0; struct timespec sleepTime; DWORD dwTimeoutSec = 15; LW_BAIL_ON_INVALID_STRING(pszServerName); LW_BAIL_ON_INVALID_STRING(pszServerAddress); for (dwAttempt = 1; dwAttempt <= 3; dwAttempt++) { // dwTimeoutSec controls how long openldap will wait for the connection // to be established. For the first attempt, this is set to 15 seconds // (which is the same amount of time netlogon will wait to get the dc // name). The second attempt halves the value to 7 seconds. The third // attempt halves it again to 3 seconds. dwError = LwLdapOpenDirectoryServerSingleAttempt( pszServerAddress, pszServerName, dwTimeoutSec, dwFlags, &pDirectory); if (dwError == ETIMEDOUT) { LW_ASSERT(pDirectory == NULL); LW_RTL_LOG_ERROR("The ldap connection to %s was disconnected. This was attempt #%d", pszServerAddress, dwAttempt); dwTimeoutSec /= 2; // This is the amount of time to sleep before trying to reconnect // again. It is: .1 seconds * dwAttempt sleepTime.tv_sec = 0; sleepTime.tv_nsec = dwAttempt * 100000000; while (nanosleep(&sleepTime, &sleepTime) == -1) { if (errno != EINTR) { dwError = LwMapErrnoToLwError(errno); BAIL_ON_LW_ERROR(dwError); } } continue; } BAIL_ON_LW_ERROR(dwError); break; } *phDirectory = (HANDLE)pDirectory; cleanup: return(dwError); error: if (pDirectory) { LwLdapCloseDirectory(pDirectory); } *phDirectory = (HANDLE)NULL; goto cleanup; }
DWORD CheckSambaVersion( PCSTR pSmbdPath, PSTR *ppVersion ) { DWORD error = 0; PCSTR ppArgs[] = { pSmbdPath, "-V", 0 }; PSTR pVersionString = NULL; error = CaptureOutputWithStderr( pSmbdPath, ppArgs, &pVersionString, NULL); BAIL_ON_LSA_ERROR(error); if (!strncmp(pVersionString, "Version ", sizeof("Version ") -1)) { memmove( pVersionString, pVersionString + (sizeof("Version ") - 1), strlen(pVersionString) - (sizeof("Version ") - 1) + 1); } LwStripWhitespace( pVersionString, TRUE, TRUE); LW_RTL_LOG_ERROR("Found smbd version %s", pVersionString); if (!strncmp(pVersionString, "3.2.", sizeof("3.2.") - 1)) { } else if (!strncmp(pVersionString, "3.4.", sizeof("3.4.") - 1)) { } else if (!strncmp(pVersionString, "3.5.", sizeof("3.5.") - 1)) { } else if (!strncmp(pVersionString, "3.6.", sizeof("3.6.") - 1)) { } else if (!strncmp(pVersionString, "3.0.", sizeof("3.0.") - 1)) { int build = 0; sscanf(pVersionString, "3.0.%d.", &build); if (build < 25) { LW_RTL_LOG_ERROR("Unsupported smbd version %s", pVersionString); error = ERROR_PRODUCT_VERSION; BAIL_ON_LSA_ERROR(error); } } else if (!strncmp(pVersionString, "4.", sizeof("4.") - 1)) { } else { LW_RTL_LOG_ERROR("Unsupported smbd version %s", pVersionString); error = ERROR_PRODUCT_VERSION; BAIL_ON_LSA_ERROR(error); } cleanup: if (error) { LW_SAFE_FREE_STRING(pVersionString); } *ppVersion = pVersionString; return error; }
DWORD LwLdapDirectorySearchEx( HANDLE hDirectory, PCSTR pszObjectDN, int scope, PCSTR pszQuery, PSTR* ppszAttributeList, LDAPControl** ppServerControls, DWORD dwNumMaxEntries, LDAPMessage** ppMessage ) { DWORD dwError = LW_ERROR_SUCCESS; PLW_LDAP_DIRECTORY_CONTEXT pDirectory = (PLW_LDAP_DIRECTORY_CONTEXT)hDirectory; struct timeval timeout = {0}; LDAPMessage* pMessage = NULL; // Set timeout to 60 seconds to be able to deal with large group // Instead of bailing on errors timeout.tv_sec = 60; timeout.tv_usec = 0; dwError = ldap_search_ext_s( pDirectory->ld, pszObjectDN, scope, pszQuery, ppszAttributeList, 0, ppServerControls, NULL, &timeout, dwNumMaxEntries, &pMessage); if (dwError) { if (dwError == LDAP_NO_SUCH_OBJECT) { LW_RTL_LOG_VERBOSE("Caught LDAP_NO_SUCH_OBJECT Error on ldap search"); BAIL_ON_LDAP_ERROR(dwError); } if (dwError == LDAP_REFERRAL) { LW_RTL_LOG_ERROR("Caught LDAP_REFERRAL Error on ldap search"); LW_RTL_LOG_ERROR("LDAP Search Info: DN: [%s]", LW_IS_NULL_OR_EMPTY_STR(pszObjectDN) ? "<null>" : pszObjectDN); LW_RTL_LOG_ERROR("LDAP Search Info: scope: [%d]", scope); LW_RTL_LOG_ERROR("LDAP Search Info: query: [%s]", LW_IS_NULL_OR_EMPTY_STR(pszQuery) ? "<null>" : pszQuery); if (ppszAttributeList) { size_t i; for (i = 0; ppszAttributeList[i] != NULL; i++) { LW_RTL_LOG_ERROR("LDAP Search Info: attribute: [%s]", ppszAttributeList[i]); } } else { LW_RTL_LOG_ERROR("Error: LDAP Search Info: no attributes were specified"); } } BAIL_ON_LDAP_ERROR(dwError); } *ppMessage = pMessage; cleanup: return(dwError); error: *ppMessage = NULL; if (pMessage) { ldap_msgfree(pMessage); } goto cleanup; }
DWORD UninstallWbclient( PCSTR pSmbdPath ) { DWORD error = 0; PSTR pSambaDir = NULL; PSTR pWbClient = NULL; PSTR pWbClientOriginal = NULL; PCSTR pLikewiseWbClient = LIBDIR "/" WBCLIENT_FILENAME; char pBuffer[1024] = { 0 }; struct stat statBuf = { 0 }; error = GetWbclientDir( pSmbdPath, &pSambaDir); BAIL_ON_LSA_ERROR(error); error = LwAllocateStringPrintf( &pWbClient, "%s/%s", pSambaDir, WBCLIENT_FILENAME ); BAIL_ON_LSA_ERROR(error); if (readlink(pWbClient, pBuffer, sizeof(pBuffer)) < 0) { switch(errno) { // File does not exist case ENOENT: // Not a symbolic link case EINVAL: pBuffer[0] = 0; break; default: error = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(error); } } pBuffer[sizeof(pBuffer) - 1] = 0; if (strcmp(pBuffer, pLikewiseWbClient)) { LW_RTL_LOG_INFO("Path %s is not a symbolic link or does not point to %s", pWbClient, pLikewiseWbClient); // Already configured goto cleanup; } error = LwAllocateStringPrintf( &pWbClientOriginal, "%s.lwidentity.orig", pWbClient ); BAIL_ON_LSA_ERROR(error); if (unlink(pWbClient) < 0) { error = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(error); } if (stat(pWbClientOriginal, &statBuf) < 0) { if (errno == ENOENT) { // This is probably Samba 3.0.x, and it did not have an original // libwbclient.so. } else { LW_RTL_LOG_ERROR("Cannot find original wbclient library at %s", pWbClientOriginal); error = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(error); } } else { if (symlink(pWbClientOriginal, pWbClient) < 0) { error = LwMapErrnoToLwError(errno); BAIL_ON_LSA_ERROR(error); } LW_RTL_LOG_INFO("Linked %s to %s", pWbClient, pLikewiseWbClient); } cleanup: LW_SAFE_FREE_STRING(pSambaDir); LW_SAFE_FREE_STRING(pWbClient); LW_SAFE_FREE_STRING(pWbClientOriginal); return error; }
NTSTATUS RtlCreateAccessToken( OUT PACCESS_TOKEN* AccessToken, IN PTOKEN_USER User, IN PTOKEN_GROUPS Groups, IN PTOKEN_PRIVILEGES Privileges, IN PTOKEN_OWNER Owner, IN PTOKEN_PRIMARY_GROUP PrimaryGroup, IN PTOKEN_DEFAULT_DACL DefaultDacl, IN OPTIONAL PTOKEN_UNIX Unix ) { NTSTATUS status = STATUS_SUCCESS; int unixError = 0; ULONG requiredSize = 0; PACCESS_TOKEN token = NULL; ULONG i = 0; ULONG size = 0; PVOID location = NULL; if (!User || !User->User.Sid || !Groups || !Owner || !PrimaryGroup || !DefaultDacl) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } if (!RtlValidSid(User->User.Sid) || (Owner->Owner && !RtlValidSid(Owner->Owner)) || (PrimaryGroup->PrimaryGroup && !RtlValidSid(PrimaryGroup->PrimaryGroup))) { status = STATUS_INVALID_SID; GOTO_CLEANUP(); } // No user attributes currently exist. if (User->User.Attributes != 0) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } for (i = 0; i < Groups->GroupCount; i++) { // TODO-Perhaps validate Group attributes if (!Groups->Groups[i].Sid) { status = STATUS_INVALID_PARAMETER; GOTO_CLEANUP(); } if (!RtlValidSid(Groups->Groups[i].Sid)) { status = STATUS_INVALID_SID; GOTO_CLEANUP(); } } if (DefaultDacl->DefaultDacl && !RtlValidAcl(DefaultDacl->DefaultDacl, NULL)) { status = STATUS_INVALID_ACL; GOTO_CLEANUP(); } // Compute size required requiredSize = sizeof(*token); size = RtlLengthSid(User->User.Sid); status = RtlSafeAddULONG(&requiredSize, requiredSize, size); GOTO_CLEANUP_ON_STATUS(status); if (Owner->Owner) { size = RtlLengthSid(Owner->Owner); status = RtlSafeAddULONG(&requiredSize, requiredSize, size); GOTO_CLEANUP_ON_STATUS(status); } if (PrimaryGroup->PrimaryGroup) { size = RtlLengthSid(PrimaryGroup->PrimaryGroup); status = RtlSafeAddULONG(&requiredSize, requiredSize, size); GOTO_CLEANUP_ON_STATUS(status); } if (DefaultDacl->DefaultDacl) { status = RtlSafeAddULONG(&requiredSize, requiredSize, DefaultDacl->DefaultDacl->AclSize); GOTO_CLEANUP_ON_STATUS(status); } status = RtlSafeMultiplyULONG(&size, sizeof(Groups->Groups[0]), Groups->GroupCount); GOTO_CLEANUP_ON_STATUS(status); status = RtlSafeAddULONG(&requiredSize, requiredSize, size); GOTO_CLEANUP_ON_STATUS(status); for (i = 0; i < Groups->GroupCount; i++) { size = RtlLengthSid(Groups->Groups[i].Sid); status = RtlSafeAddULONG(&requiredSize, requiredSize, size); GOTO_CLEANUP_ON_STATUS(status); } status = RtlSafeMultiplyULONG(&size, sizeof(Privileges->Privileges[0]), Privileges->PrivilegeCount); GOTO_CLEANUP_ON_STATUS(status); status = RtlSafeAddULONG(&requiredSize, requiredSize, size); GOTO_CLEANUP_ON_STATUS(status); status = RTL_ALLOCATE(&token, ACCESS_TOKEN, requiredSize); GOTO_CLEANUP_ON_STATUS(status); location = LW_PTR_ADD(token, sizeof(*token)); // Initialize token->ReferenceCount = 1; token->Flags = 0; unixError = pthread_rwlock_init(&token->RwLock, NULL); if (unixError) { LW_RTL_LOG_ERROR("Failed to init rwlock in access token " "(error = %d).", unixError); status = LwErrnoToNtStatus(unixError); GOTO_CLEANUP(); } token->pRwLock = &token->RwLock; token->User.Attributes = User->User.Attributes; token->User.Sid = (PSID) location; location = RtlpAppendData(location, User->User.Sid, RtlLengthSid(User->User.Sid)); token->GroupCount = Groups->GroupCount; token->Groups = (PSID_AND_ATTRIBUTES) location; location = LwRtlOffsetToPointer(location, sizeof(Groups->Groups[0]) * Groups->GroupCount); for (i = 0; i < Groups->GroupCount; i++) { token->Groups[i].Attributes = Groups->Groups[i].Attributes; token->Groups[i].Sid = (PSID) location; location = RtlpAppendData(location, Groups->Groups[i].Sid, RtlLengthSid(Groups->Groups[i].Sid)); } token->PrivilegeCount = Privileges->PrivilegeCount; token->Privileges = (PLUID_AND_ATTRIBUTES) location; location = LwRtlOffsetToPointer( location, sizeof(Privileges->Privileges[0]) * Privileges->PrivilegeCount); memcpy(token->Privileges, Privileges->Privileges, sizeof(token->Privileges[0]) * token->PrivilegeCount); if (Owner->Owner) { token->Owner = (PSID) location; location = RtlpAppendData(location, Owner->Owner, RtlLengthSid(Owner->Owner)); } if (PrimaryGroup->PrimaryGroup) { token->PrimaryGroup = (PSID) location; location = RtlpAppendData(location, PrimaryGroup->PrimaryGroup, RtlLengthSid(PrimaryGroup->PrimaryGroup)); } if (DefaultDacl->DefaultDacl) { token->DefaultDacl = (PACL) location; location = RtlpAppendData(location, DefaultDacl->DefaultDacl, DefaultDacl->DefaultDacl->AclSize); } if (Unix) { SetFlag(token->Flags, ACCESS_TOKEN_FLAG_UNIX_PRESENT); token->Uid = Unix->Uid; token->Gid = Unix->Gid; token->Umask = Unix->Umask; } if (location != LW_PTR_ADD(token, requiredSize)) { status = STATUS_ASSERTION_FAILURE; GOTO_CLEANUP(); } status = STATUS_SUCCESS; cleanup: if (!NT_SUCCESS(status)) { RtlReleaseAccessToken(&token); } *AccessToken = token; return status; }