LW_NTSTATUS LwRtlSvcmLoadEmbedded( LW_IN LW_PCWSTR pServiceName, LW_IN LW_SVCM_MODULE_ENTRY_FUNCTION Entry, LW_OUT PLW_SVCM_INSTANCE* ppInstance ) { NTSTATUS status = STATUS_SUCCESS; PLW_SVCM_INSTANCE pInstance = NULL; status = InitPool(); GCOS(status); status = LW_RTL_ALLOCATE_AUTO(&pInstance); GCOS(status); LW_RTL_LOG_DEBUG("Loading embedded service: %s", pServiceName); status = LwRtlSvcmInitializeInstance(pInstance, pServiceName, "<embedded>", Entry); GCOS(status); cleanup: if (!NT_SUCCESS(status)) { LwRtlSvcmUnload(pInstance); pInstance = NULL; } *ppInstance = pInstance; return status; }
DWORD LwKrb5SetThreadDefaultCachePath( IN PCSTR pszCachePath, OUT PSTR* ppszPreviousCachePath ) { DWORD dwError = 0; DWORD dwMajorStatus = 0; DWORD dwMinorStatus = 0; PSTR pszOrigCachePath = NULL; // Set the default for gss dwMajorStatus = gss_krb5_ccache_name( (OM_uint32 *)&dwMinorStatus, pszCachePath, (ppszPreviousCachePath) ? (const char**)&pszOrigCachePath : NULL); BAIL_ON_GSS_ERROR(dwError, dwMajorStatus, dwMinorStatus); LW_RTL_LOG_DEBUG("Switched gss krb5 credentials path from %s to %s", LW_SAFE_LOG_STRING(pszOrigCachePath), LW_SAFE_LOG_STRING(pszCachePath)); if (ppszPreviousCachePath) { if (!LW_IS_NULL_OR_EMPTY_STR(pszOrigCachePath)) { dwError = LwAllocateString(pszOrigCachePath, ppszPreviousCachePath); BAIL_ON_LW_ERROR(dwError); } else { *ppszPreviousCachePath = NULL; } } cleanup: return dwError; error: if (ppszPreviousCachePath) { *ppszPreviousCachePath = NULL; } goto cleanup; }
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; }
// 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; }