/* Editor Settings: expandtabs and use 4 spaces for indentation * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: * * -*- mode: c, c-basic-offset: 4 -*- */ /* * Copyright Likewise Software 2004-2008 * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. You should have received a copy of the GNU General * Public License along with this program. If not, see * . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ /* * Copyright (C) Likewise Software. All rights reserved. * * Module Name: * * provider-main.c * * Abstract: * * Likewise Security and Authentication Subsystem (LSASS) * * AD LDAP User Marshalling * * Authors: Krishna Ganugapati (krishnag@likewisesoftware.com) * Sriram Nambakam (snambakam@likewisesoftware.com) * Wei Fu (wfu@likewisesoftware.com) * Brian Dunstan (bdunstan@likewisesoftware.com) * Kyle Stemen (kstemen@likewisesoftware.com) */ #include "adprovider.h" DWORD ADGetCurrentNtTime( OUT UINT64* pqwResult ) { DWORD dwError = LW_ERROR_SUCCESS; time_t now = 0; dwError = LsaGetCurrentTimeSeconds(&now); BAIL_ON_LSA_ERROR(dwError); dwError = ADConvertTimeUnix2Nt(now, pqwResult); BAIL_ON_LSA_ERROR(dwError); cleanup: return dwError; error: *pqwResult = 0; goto cleanup; } DWORD ADConvertTimeNt2Unix( UINT64 ntTime, PUINT64 pUnixTime ) { UINT64 unixTime = 0; unixTime = ntTime/10000000LL - 11644473600LL; *pUnixTime = unixTime; return 0; } DWORD ADConvertTimeUnix2Nt( UINT64 unixTime, PUINT64 pNtTime ) { UINT64 ntTime = 0; ntTime = (unixTime+11644473600LL)*10000000LL; *pNtTime = ntTime; return 0; } DWORD ADNonSchemaKeywordGetString( PSTR *ppszValues, DWORD dwNumValues, PCSTR pszAttributeName, PSTR *ppszResult ) { DWORD dwError = 0; size_t i; size_t sNameLen = strlen(pszAttributeName); PSTR pszResult = NULL; for (i = 0; i < dwNumValues; i++) { PCSTR pszValue = ppszValues[i]; // Look for ldap values which are in the form = if (!strncasecmp(pszValue, pszAttributeName, sNameLen) && pszValue[sNameLen] == '=') { dwError = LwAllocateString( pszValue + sNameLen + 1, &pszResult); BAIL_ON_LSA_ERROR(dwError); break; } } *ppszResult = pszResult; cleanup: return dwError; error: *ppszResult = NULL; LW_SAFE_FREE_STRING(pszResult); goto cleanup; } DWORD ADNonSchemaKeywordGetUInt32( PSTR *ppszValues, DWORD dwNumValues, PCSTR pszAttributeName, DWORD *pdwResult ) { size_t i; size_t sNameLen = strlen(pszAttributeName); for (i = 0; i < dwNumValues; i++) { PCSTR pszValue = ppszValues[i]; // Don't free this PSTR pszEndPtr = NULL; // Look for ldap values which are in the form = if (!strncasecmp(pszValue, pszAttributeName, sNameLen) && pszValue[sNameLen] == '=') { pszValue += sNameLen + 1; *pdwResult = strtoul(pszValue, &pszEndPtr, 10); if (pszEndPtr == NULL || *pszEndPtr != '\0' || pszEndPtr == pszValue) { // Couldn't parse the whole number return LW_ERROR_INVALID_LDAP_ATTR_VALUE; } return LW_ERROR_SUCCESS; } } // Couldn't find the attribute return LW_ERROR_INVALID_LDAP_ATTR_VALUE; } DWORD AD_BuildHomeDirFromTemplate( PCSTR pszHomedirTemplate, PCSTR pszNetBIOSDomainName, PCSTR pszSamAccountName, PSTR* ppszHomedir ) { DWORD dwError = 0; PSTR pszHomedirPrefix = NULL; PSTR pszHomedir = NULL; DWORD dwOffset = 0; PCSTR pszIterTemplate = pszHomedirTemplate; DWORD dwBytesAllocated = 0; DWORD dwNetBIOSDomainNameLength = 0; DWORD dwSamAccountNameLength = 0; DWORD dwHomedirPrefixLength = 0; PSTR pszHostName = NULL; DWORD dwHostNameLength = 0; BAIL_ON_INVALID_STRING(pszHomedirTemplate); BAIL_ON_INVALID_STRING(pszNetBIOSDomainName); BAIL_ON_INVALID_STRING(pszSamAccountName); if (strstr(pszHomedirTemplate, "%H")) { dwError = AD_GetHomedirPrefixPath(&pszHomedirPrefix); BAIL_ON_LSA_ERROR(dwError); BAIL_ON_INVALID_STRING(pszHomedirPrefix); dwHomedirPrefixLength = strlen(pszHomedirPrefix); } if (strstr(pszHomedirTemplate, "%L")) { dwError = LsaDnsGetHostInfo(&pszHostName); BAIL_ON_LSA_ERROR(dwError); BAIL_ON_INVALID_STRING(pszHostName); dwHostNameLength = strlen(pszHostName); } dwNetBIOSDomainNameLength = strlen(pszNetBIOSDomainName); dwSamAccountNameLength = strlen(pszSamAccountName); // Handle common case where we might use all replacements. dwBytesAllocated = (strlen(pszHomedirTemplate) + dwNetBIOSDomainNameLength + dwSamAccountNameLength + dwHomedirPrefixLength + dwHostNameLength + 1); dwError = LwAllocateMemory( sizeof(CHAR) * dwBytesAllocated, (PVOID*)&pszHomedir); BAIL_ON_LSA_ERROR(dwError); while (pszIterTemplate[0]) { // Do not count the terminating NULL as "available". DWORD dwBytesRemaining = dwBytesAllocated - dwOffset - 1; PCSTR pszInsert = NULL; DWORD dwInsertLength = 0; BOOLEAN bNeedUpper = FALSE; BOOLEAN bNeedLower = FALSE; LSA_ASSERT(dwOffset < dwBytesAllocated); if (pszIterTemplate[0] == '%') { switch (pszIterTemplate[1]) { case 'D': pszInsert = pszNetBIOSDomainName; dwInsertLength = dwNetBIOSDomainNameLength; bNeedUpper = TRUE; break; case 'U': pszInsert = pszSamAccountName; dwInsertLength = dwSamAccountNameLength; bNeedLower = TRUE; break; case 'H': pszInsert = pszHomedirPrefix; dwInsertLength = dwHomedirPrefixLength; break; case 'L': pszInsert = pszHostName; dwInsertLength = dwHostNameLength; break; default: dwError = LW_ERROR_INVALID_HOMEDIR_TEMPLATE; BAIL_ON_LSA_ERROR(dwError); } LSA_ASSERT(!(bNeedUpper && bNeedLower)); pszIterTemplate += 2; } else { PCSTR pszEnd = strchr(pszIterTemplate, '%'); if (!pszEnd) { dwInsertLength = strlen(pszIterTemplate); } else { dwInsertLength = pszEnd - pszIterTemplate; } pszInsert = pszIterTemplate; pszIterTemplate += dwInsertLength; } if (dwBytesRemaining < dwInsertLength) { // We will increment by at least a minimum amount. DWORD dwAllocate = LSA_MAX(dwInsertLength - dwBytesRemaining, 64); PSTR pszNewHomedir = NULL; dwError = LwReallocMemory( pszHomedir, (PVOID*)&pszNewHomedir, dwBytesAllocated + dwAllocate); BAIL_ON_LSA_ERROR(dwError); pszHomedir = pszNewHomedir; dwBytesAllocated += dwAllocate; } memcpy(pszHomedir + dwOffset, pszInsert, dwInsertLength); if (bNeedUpper) { LwStrnToUpper(pszHomedir + dwOffset, dwInsertLength); } else if (bNeedLower) { LwStrnToLower(pszHomedir + dwOffset, dwInsertLength); } dwOffset += dwInsertLength; } // We should still have enough room for NULL. LSA_ASSERT(dwOffset < dwBytesAllocated); pszHomedir[dwOffset] = 0; dwOffset++; *ppszHomedir = pszHomedir; cleanup: LW_SAFE_FREE_STRING(pszHomedirPrefix); LW_SAFE_FREE_STRING(pszHostName); return dwError; error: *ppszHomedir = NULL; LW_SAFE_FREE_MEMORY(pszHomedir); goto cleanup; } /* local variables: mode: c c-basic-offset: 4 indent-tabs-mode: nil tab-width: 4 end: */