DWORD LsaPstorepBackendDeletePasswordInfoW( IN PLSA_PSTORE_BACKEND_STATE State, IN PCWSTR DnsDomainName ) { DWORD dwError = 0; int EE = 0; PSTR dnsDomainNameA = NULL; dwError = LwNtStatusToWin32Error(LwRtlCStringAllocateFromWC16String( &dnsDomainNameA, DnsDomainName)); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); dwError = LwpsLegacyDeletePassword( State->OldStoreHandle, dnsDomainNameA); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); cleanup: LW_RTL_FREE(&dnsDomainNameA); LSA_PSTORE_LOG_LEAVE_ERROR_EE(dwError, EE); return dwError; }
DWORD LsaPstorepBackendSetDefaultDomainW( IN PLSA_PSTORE_BACKEND_STATE State, IN OPTIONAL PCWSTR DnsDomainName ) { DWORD dwError = 0; int EE = 0; PSTR dnsDomainNameA = NULL; if (DnsDomainName) { dwError = LwNtStatusToWin32Error(LwRtlCStringAllocateFromWC16String( &dnsDomainNameA, DnsDomainName)); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); } dwError = LwpsLegacySetDefaultJoinedDomain( State->OldStoreHandle, dnsDomainNameA); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); cleanup: LW_RTL_FREE(&dnsDomainNameA); LSA_PSTORE_LOG_LEAVE_ERROR_EE(dwError, EE); return dwError; }
DWORD LsaPstoreGetDefaultDomainA( OUT PSTR* DnsDomainName ) { DWORD dwError = 0; int EE = 0; PWSTR dnsDomainNameW = NULL; PSTR dnsDomainName = NULL; dwError = LsaPstoreGetDefaultDomainW(&dnsDomainNameW); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); dwError = LwNtStatusToWin32Error(LwRtlCStringAllocateFromWC16String( &dnsDomainName, dnsDomainNameW)); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); cleanup: if (dwError) { LW_RTL_FREE(&dnsDomainName); } LSA_PSTORE_FREE(&dnsDomainNameW); *DnsDomainName = dnsDomainName; LSA_PSTORE_LOG_LEAVE_ERROR_EE(dwError, EE); return dwError; }
DWORD RegCStringAllocateFromWC16String( OUT PSTR* ppszNewString, IN PCWSTR pszOriginalString ) { return RegNtStatusToWin32Error( LwRtlCStringAllocateFromWC16String(ppszNewString, pszOriginalString) ); }
DWORD LsaPstoreGetJoinedDomainsA( OUT PSTR** DnsDomainNames, OUT PDWORD Count ) { DWORD dwError = 0; int EE = 0; PSTR* dnsDomainNames = NULL; DWORD count = 0; PWSTR* dnsDomainNamesW = NULL; DWORD countW = 0; dwError = LsaPstoreGetJoinedDomainsW( &dnsDomainNamesW, &countW); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); if (!countW) { GOTO_CLEANUP_EE(EE); } dwError = LwNtStatusToWin32Error(LW_RTL_ALLOCATE( &dnsDomainNames, VOID, countW * sizeof(dnsDomainNames[0]))); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); for (count = 0; count < countW; count++) { dwError = LwNtStatusToWin32Error(LwRtlCStringAllocateFromWC16String( &dnsDomainNames[count], dnsDomainNamesW[count])); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); } cleanup: if (dwError) { LSA_PSTORE_FREE_STRING_ARRAY_A(&dnsDomainNames, &count); } LSA_PSTORE_FREE_STRING_ARRAY_W(&dnsDomainNamesW, &countW); *DnsDomainNames = dnsDomainNames; *Count = count; LSA_PSTORE_LOG_LEAVE_ERROR_EE(dwError, EE); return dwError; }
DWORD LsaPstorepBackendGetPasswordInfoW( IN PLSA_PSTORE_BACKEND_STATE State, IN PCWSTR DnsDomainName, OUT OPTIONAL PLSA_MACHINE_PASSWORD_INFO_W* PasswordInfo ) { DWORD dwError = 0; int EE = 0; PSTR dnsDomainNameA = NULL; PLSA_MACHINE_PASSWORD_INFO_W passwordInfo = NULL; PLSA_MACHINE_PASSWORD_INFO_A passwordInfoA = NULL; dwError = LwNtStatusToWin32Error(LwRtlCStringAllocateFromWC16String( &dnsDomainNameA, DnsDomainName)); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); dwError = LwpsLegacyReadPassword( State->OldStoreHandle, dnsDomainNameA, &passwordInfoA); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); dwError = LsaPstorepConvertAnsiToWidePasswordInfo( passwordInfoA, &passwordInfo); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); cleanup: if (dwError) { LSA_PSTORE_FREE_PASSWORD_INFO_W(&passwordInfo); } LSA_PSTORE_FREE_PASSWORD_INFO_A(&passwordInfoA); LW_RTL_FREE(&dnsDomainNameA); if (PasswordInfo) { *PasswordInfo = passwordInfo; } else { LSA_PSTORE_FREE_PASSWORD_INFO_W(&passwordInfo); } LSA_PSTORE_LOG_LEAVE_ERROR_EE(dwError, EE); return dwError; }
DWORD ConvertUnicodetoAnsiString( PCWSTR pwszSrc, PSTR* ppszDst ) { DWORD dwError = 0; #ifdef _WIN32 PSTR pszNewString = NULL; #endif if (!pwszSrc || !ppszDst) { dwError = ERROR_INVALID_PARAMETER; } else { #ifdef _WIN32 ULONG srcLen = (ULONG)wcslen(pwszSrc)+1; ULONG destLen = srcLen*2; dwError = VMCAAllocateMemory((DWORD) destLen, (PVOID*)&pszNewString); BAIL_ON_ERROR(dwError); if (0 == WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, pszNewString, destLen, NULL, NULL )) { dwError = GetLastError(); BAIL_ON_ERROR(dwError); } *ppszDst = pszNewString; cleanup: return dwError; error: VMCAFreeMemory(pszNewString); goto cleanup; #else dwError = LwNtStatusToWin32Error( LwRtlCStringAllocateFromWC16String(ppszDst, pwszSrc)); #endif } return dwError; }
ULONG VmDirAllocateStringAFromW( PCWSTR pwszSrc, PSTR* ppszDst ) { ULONG ulError = 0; if (!pwszSrc || !ppszDst) { ulError = ERROR_INVALID_PARAMETER; } else { ulError = LwNtStatusToWin32Error( LwRtlCStringAllocateFromWC16String(ppszDst, pwszSrc)); } return ulError; }
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; }
static NTSTATUS LwIoCredentialCacheToTgt( PIO_CREDS pCacheToken, PIO_CREDS* ppCreds ) { NTSTATUS Status = STATUS_SUCCESS; krb5_context pContext = NULL; krb5_error_code krb5Error = 0; krb5_ccache pCache = NULL; PSTR pszClientPrincipalName = NULL; PSTR pszServerPrincipalName = NULL; PSTR pszDesiredPrincipal = NULL; PSTR pszCredCachePath = NULL; PIO_CREDS pCreds = NULL; BOOLEAN bFoundTgt = FALSE; BOOLEAN bStartSeq = FALSE; krb5_creds creds; krb5_cc_cursor cursor; Status = LwRtlCStringAllocateFromWC16String( &pszDesiredPrincipal, pCacheToken->payload.krb5Ccache.pwszPrincipal); BAIL_ON_NT_STATUS(Status); Status = LwRtlCStringAllocateFromWC16String( &pszCredCachePath, pCacheToken->payload.krb5Ccache.pwszCachePath); BAIL_ON_NT_STATUS(Status); /* Open credentials cache */ krb5Error = krb5_init_context(&pContext); if (krb5Error) { Status = STATUS_INSUFFICIENT_RESOURCES; BAIL_ON_NT_STATUS(Status); } krb5Error = krb5_cc_resolve(pContext, pszCredCachePath, &pCache); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } /* Look for a TGT */ krb5Error = krb5_cc_start_seq_get(pContext, pCache, &cursor); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } bStartSeq = TRUE; while ((krb5Error = krb5_cc_next_cred(pContext, pCache, &cursor, &creds)) == 0) { /* Look tickets with the intial flag set */ if (creds.ticket_flags & TKT_FLG_INITIAL) { /* Extract and compare client principal with desired principal */ krb5Error = krb5_unparse_name(pContext, creds.client, &pszClientPrincipalName); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } if (!strcmp(pszClientPrincipalName, pszDesiredPrincipal)) { bFoundTgt = TRUE; break; } krb5_free_unparsed_name(pContext, pszClientPrincipalName); pszClientPrincipalName = NULL; } krb5_free_cred_contents(pContext, &creds); } if (!bFoundTgt) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } /* Extract server principal name */ krb5Error = krb5_unparse_name(pContext, creds.server, &pszServerPrincipalName); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } /* Construct token from krb5 credential data */ Status = LwIoAllocateMemory(sizeof(*pCreds), OUT_PPVOID(&pCreds)); BAIL_ON_NT_STATUS(Status); pCreds->type = IO_CREDS_TYPE_KRB5_TGT; /* Copy principal names */ Status = LwRtlWC16StringAllocateFromCString( &pCreds->payload.krb5Tgt.pwszClientPrincipal, pszClientPrincipalName); BAIL_ON_NT_STATUS(Status); Status = LwRtlWC16StringAllocateFromCString( &pCreds->payload.krb5Tgt.pwszServerPrincipal, pszServerPrincipalName); BAIL_ON_NT_STATUS(Status); /* Set time fields */ pCreds->payload.krb5Tgt.authTime = creds.times.authtime; pCreds->payload.krb5Tgt.startTime = creds.times.starttime; pCreds->payload.krb5Tgt.endTime = creds.times.endtime; pCreds->payload.krb5Tgt.renewTillTime = creds.times.renew_till; /* Copy encryption key */ pCreds->payload.krb5Tgt.keyType = creds.keyblock.enctype; pCreds->payload.krb5Tgt.ulKeySize = creds.keyblock.length; Status = LwIoAllocateMemory( creds.keyblock.length, OUT_PPVOID(&pCreds->payload.krb5Tgt.pKeyData)); BAIL_ON_NT_STATUS(Status); memcpy( pCreds->payload.krb5Tgt.pKeyData, creds.keyblock.contents, creds.keyblock.length); /* Copy tgt */ pCreds->payload.krb5Tgt.tgtFlags = creds.ticket_flags; pCreds->payload.krb5Tgt.ulTgtSize = creds.ticket.length; Status = LwIoAllocateMemory( creds.ticket.length, OUT_PPVOID(&pCreds->payload.krb5Tgt.pTgtData)); BAIL_ON_NT_STATUS(Status); memcpy( pCreds->payload.krb5Tgt.pTgtData, creds.ticket.data, creds.ticket.length); *ppCreds = pCreds; cleanup: LWIO_SAFE_FREE_MEMORY(pszDesiredPrincipal); LWIO_SAFE_FREE_MEMORY(pszCredCachePath); if (pszClientPrincipalName) { krb5_free_unparsed_name(pContext, pszClientPrincipalName); } if (pszServerPrincipalName) { krb5_free_unparsed_name(pContext, pszServerPrincipalName); } if (bFoundTgt) { krb5_free_cred_contents(pContext, &creds); } if (bStartSeq) { krb5_cc_end_seq_get(pContext, pCache, &cursor); } if (pCache) { krb5_cc_close(pContext, pCache); } if (pContext) { krb5_free_context(pContext); } return Status; error: *ppCreds = NULL; if (pCreds) { LwIoDeleteCreds(pCreds); } goto cleanup; }
NTSTATUS LwioCopyDirFromRemote( IN PCSTR pszSourcePath, IN PCSTR pszTargetPath ) { NTSTATUS status = STATUS_SUCCESS; BOOL bRestart = TRUE; IO_FILE_NAME filename = {0}; IO_FILE_HANDLE handle = NULL; IO_STATUS_BLOCK ioStatus ; PSTR pszEntryFilename = NULL; BYTE buffer[MAX_BUFFER]; PFILE_BOTH_DIR_INFORMATION pInfo = NULL; PSTR pszLocalPath = NULL; PSTR pszRemotePath = NULL; BAIL_ON_NULL_POINTER(pszSourcePath); BAIL_ON_NULL_POINTER(pszTargetPath); status = LwioRemoteOpenFile( pszSourcePath, FILE_LIST_DIRECTORY, /* Desired access mask */ FILE_SHARE_READ, /* Share access */ FILE_OPEN, /* Create disposition */ FILE_DIRECTORY_FILE, /* Create options */ &handle); BAIL_ON_NT_STATUS(status); status = LwioLocalCreateDir( pszTargetPath, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); BAIL_ON_NT_STATUS(status); for (;;) { status = LwNtQueryDirectoryFile( handle, /* File handle */ NULL, /* Async control block */ &ioStatus, /* IO status block */ buffer, /* Info structure */ sizeof(buffer), /* Info structure size */ FileBothDirectoryInformation, /* Info level */ FALSE, /* Do not return single entry */ NULL, /* File spec */ bRestart); /* Restart scan */ switch (status) { case STATUS_NO_MORE_MATCHES: status = STATUS_SUCCESS; goto cleanup; default: BAIL_ON_NT_STATUS(status); } bRestart = FALSE; for (pInfo = (PFILE_BOTH_DIR_INFORMATION) buffer; pInfo; pInfo = (pInfo->NextEntryOffset)?(PFILE_BOTH_DIR_INFORMATION) (((PBYTE) pInfo) + pInfo->NextEntryOffset):NULL) { RTL_FREE(&pszEntryFilename); RTL_FREE(&pszRemotePath); RTL_FREE(&pszLocalPath); status = LwRtlCStringAllocateFromWC16String( &pszEntryFilename, pInfo->FileName ); BAIL_ON_NT_STATUS(status); if (!strcmp(pszEntryFilename, "..") || !strcmp(pszEntryFilename, ".")) continue; status = LwRtlCStringAllocatePrintf( &pszRemotePath, "%s/%s", pszSourcePath, pszEntryFilename); BAIL_ON_NT_STATUS(status); status = LwRtlCStringAllocatePrintf( &pszLocalPath, "%s/%s", pszTargetPath, pszEntryFilename); BAIL_ON_NT_STATUS(status); if(pInfo->FileAttributes == FILE_ATTRIBUTE_DIRECTORY) { status = LwioCopyDirFromRemote( pszRemotePath, pszLocalPath); BAIL_ON_NT_STATUS(status); } else { status = LwioCopyFileFromRemote( pszRemotePath, pszLocalPath); BAIL_ON_NT_STATUS(status); } } } cleanup: if (handle) { LwNtCloseFile(handle); } RTL_FREE(&pszLocalPath); RTL_FREE(&pszRemotePath); RTL_FREE(&pszEntryFilename); RTL_FREE(&filename.FileName); return status; error: goto cleanup; }
NTSTATUS SMBCredTokenToKrb5CredCache( PIO_CREDS pCredToken, PSTR* ppszCachePath ) { NTSTATUS Status = STATUS_SUCCESS; krb5_context pContext = NULL; krb5_error_code krb5Error = 0; krb5_ccache pCache = NULL; PSTR pszClientPrincipalName = NULL; PSTR pszServerPrincipalName = NULL; PSTR pszCachePath = NULL; krb5_creds creds; memset(&creds, 0, sizeof(creds)); /* Set up an in-memory cache to receive the credentials */ Status = SMBAllocateStringPrintf( &pszCachePath, "MEMORY:%lu", (unsigned long) (size_t) ppszCachePath); BAIL_ON_NT_STATUS(Status); krb5Error = krb5_init_context(&pContext); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } krb5Error = krb5_cc_resolve(pContext, pszCachePath, &pCache); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } /* Convert cred token back into krb5 structure */ /* Convert client and server principal names */ Status = LwRtlCStringAllocateFromWC16String( &pszClientPrincipalName, pCredToken->payload.krb5Tgt.pwszClientPrincipal); BAIL_ON_NT_STATUS(Status); krb5Error = krb5_parse_name(pContext, pszClientPrincipalName, &creds.client); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } Status = LwRtlCStringAllocateFromWC16String( &pszServerPrincipalName, pCredToken->payload.krb5Tgt.pwszServerPrincipal); BAIL_ON_NT_STATUS(Status); krb5Error = krb5_parse_name(pContext, pszServerPrincipalName, &creds.server); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } /* Convert times */ creds.times.authtime = pCredToken->payload.krb5Tgt.authTime; creds.times.starttime = pCredToken->payload.krb5Tgt.startTime; creds.times.endtime = pCredToken->payload.krb5Tgt.endTime; creds.times.renew_till = pCredToken->payload.krb5Tgt.renewTillTime; /* Convert encryption key */ creds.keyblock.enctype = pCredToken->payload.krb5Tgt.keyType; creds.keyblock.length = (unsigned int) pCredToken->payload.krb5Tgt.ulKeySize; creds.keyblock.contents = pCredToken->payload.krb5Tgt.pKeyData; /* Convert tgt */ creds.ticket_flags = pCredToken->payload.krb5Tgt.tgtFlags; creds.ticket.length = pCredToken->payload.krb5Tgt.ulTgtSize; creds.ticket.data = (char*) pCredToken->payload.krb5Tgt.pTgtData; /* Initialize the credential cache with the client principal name */ krb5Error = krb5_cc_initialize(pContext, pCache, creds.client); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } /* Store the converted credentials in the cache */ krb5Error = krb5_cc_store_cred(pContext, pCache, &creds); if (krb5Error) { Status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(Status); } *ppszCachePath = pszCachePath; cleanup: LWIO_SAFE_FREE_MEMORY(pszClientPrincipalName); LWIO_SAFE_FREE_MEMORY(pszServerPrincipalName); if (creds.client) { krb5_free_principal(pContext, creds.client); } if (creds.server) { krb5_free_principal(pContext, creds.server); } if (pCache) { krb5_cc_close(pContext, pCache); } if (pContext) { krb5_free_context(pContext); } return Status; error: *ppszCachePath = NULL; LWIO_SAFE_FREE_MEMORY(pszCachePath); goto cleanup; }
DWORD SMBGSSContextBuild( PCWSTR pwszServerName, PIO_CREDS pCreds, PHANDLE phSMBGSSContext ) { DWORD dwError = 0; DWORD dwMajorStatus = 0; DWORD dwMinorStatus = 0; PSMB_GSS_SEC_CONTEXT pContext = NULL; PSTR pszTargetName = NULL; PSTR pszServerName = NULL; PSTR pszUsername = NULL; PSTR pszDomain = NULL; PSTR pszPassword = NULL; gss_buffer_desc usernameBuffer = {0}; gss_buffer_desc inputNameBuffer = {0}; gss_buffer_desc authDataBuffer = {0}; gss_name_t pUsername = NULL; gss_OID_set_desc desiredMechs; gss_OID_set actualMechs; OM_uint32 timeRec = 0; SEC_WINNT_AUTH_IDENTITY authData; static gss_OID_desc gssCredOptionPasswordOidDesc = { .length = GSS_CRED_OPT_PW_LEN, .elements = GSS_CRED_OPT_PW }; static gss_OID_desc gssNtlmOidDesc = { .length = GSS_MECH_NTLM_LEN, .elements = GSS_MECH_NTLM }; size_t sCopyServerChars = 0; dwError = LwRtlCStringAllocateFromWC16String(&pszServerName, pwszServerName); BAIL_ON_LWIO_ERROR(dwError); LWIO_LOG_DEBUG("Build GSS Context for server [%s]", LWIO_SAFE_LOG_STRING(pszServerName)); dwError = LwIoAllocateMemory( sizeof(SMB_GSS_SEC_CONTEXT), (PVOID*)&pContext); BAIL_ON_LWIO_ERROR(dwError); pContext->state = SMB_GSS_SEC_CONTEXT_STATE_INITIAL; if (pCreds) { switch (pCreds->type) { case IO_CREDS_TYPE_KRB5_CCACHE: dwError = STATUS_ACCESS_DENIED; BAIL_ON_LWIO_ERROR(dwError); break; case IO_CREDS_TYPE_KRB5_TGT: sCopyServerChars = strlen(pszServerName); if (sCopyServerChars > 0 && pszServerName[sCopyServerChars - 1] == '.') { // Strip the trailing dot sCopyServerChars --; } if (sCopyServerChars > INT_MAX) { dwError = STATUS_INTEGER_OVERFLOW; BAIL_ON_LWIO_ERROR(dwError); } dwError = SMBAllocateStringPrintf( &pszTargetName, "cifs/%.*s@", (int)sCopyServerChars, pszServerName); BAIL_ON_LWIO_ERROR(dwError); inputNameBuffer.value = pszTargetName; inputNameBuffer.length = strlen(pszTargetName) + 1; dwMajorStatus = gss_import_name( (OM_uint32 *)&dwMinorStatus, &inputNameBuffer, (gss_OID) gss_nt_krb5_name, &pContext->target_name); smb_display_status("gss_import_name", dwMajorStatus, dwMinorStatus); BAIL_ON_SEC_ERROR(dwMajorStatus); dwError = LwRtlCStringAllocateFromWC16String( &pszUsername, pCreds->payload.krb5Tgt.pwszClientPrincipal); BAIL_ON_NT_STATUS(dwError); usernameBuffer.value = pszUsername; usernameBuffer.length = strlen(pszUsername) + 1; dwMajorStatus = gss_import_name( (OM_uint32 *)&dwMinorStatus, &usernameBuffer, GSS_C_NT_USER_NAME, &pUsername); BAIL_ON_SEC_ERROR(dwMajorStatus); desiredMechs.count = 1; desiredMechs.elements = (gss_OID) gss_mech_krb5; dwMajorStatus = gss_acquire_cred( (OM_uint32 *)&dwMinorStatus, pUsername, 0, &desiredMechs, GSS_C_INITIATE, &pContext->credHandle, &actualMechs, &timeRec); BAIL_ON_SEC_ERROR(dwMajorStatus); break; case IO_CREDS_TYPE_PLAIN: inputNameBuffer.value = (void*) "unset"; inputNameBuffer.length = strlen("unset"); dwMajorStatus = gss_import_name( (OM_uint32 *)&dwMinorStatus, &inputNameBuffer, (gss_OID) gss_nt_krb5_name, &pContext->target_name); smb_display_status("gss_import_name", dwMajorStatus, dwMinorStatus); BAIL_ON_SEC_ERROR(dwMajorStatus); if (pCreds->payload.plain.pwszUsername) { dwError = LwRtlCStringAllocateFromWC16String(&pszUsername, pCreds->payload.plain.pwszUsername); BAIL_ON_LWIO_ERROR(dwError); usernameBuffer.value = pszUsername; usernameBuffer.length = strlen(pszUsername); // If "" is passed in, that means to use anonymous // authentication. gss_import_name fails on "" though if (usernameBuffer.length) { dwMajorStatus = gss_import_name( (OM_uint32 *)&dwMinorStatus, &usernameBuffer, GSS_C_NT_USER_NAME, &pUsername); BAIL_ON_SEC_ERROR(dwMajorStatus); } } desiredMechs.count = 1; desiredMechs.elements = (gss_OID) &gssNtlmOidDesc; dwMajorStatus = gss_acquire_cred( (OM_uint32 *)&dwMinorStatus, pUsername, 0, &desiredMechs, GSS_C_INITIATE, &pContext->credHandle, &actualMechs, &timeRec); BAIL_ON_SEC_ERROR(dwMajorStatus); if (pCreds->payload.plain.pwszUsername && pCreds->payload.plain.pwszPassword && pCreds->payload.plain.pwszDomain) { dwError = LwRtlCStringAllocateFromWC16String(&pszDomain, pCreds->payload.plain.pwszDomain); BAIL_ON_LWIO_ERROR(dwError); dwError = LwRtlCStringAllocateFromWC16String(&pszPassword, pCreds->payload.plain.pwszPassword); BAIL_ON_LWIO_ERROR(dwError); authData.User = pszUsername; authData.UserLength = strlen(pszUsername); authData.Domain = pszDomain; authData.DomainLength = strlen(pszDomain); authData.Password = pszPassword; authData.PasswordLength = strlen(pszPassword); authData.Flags = 0; authDataBuffer.value = &authData; authDataBuffer.length = sizeof(authData); dwMajorStatus = gssspi_set_cred_option( (OM_uint32 *)&dwMinorStatus, pContext->credHandle, (gss_OID) &gssCredOptionPasswordOidDesc, &authDataBuffer); BAIL_ON_SEC_ERROR(dwMajorStatus); } break; } } dwError = LwIoAllocateMemory( sizeof(CtxtHandle), (PVOID*)&pContext->pGSSContext); BAIL_ON_LWIO_ERROR(dwError); *pContext->pGSSContext = GSS_C_NO_CONTEXT; *phSMBGSSContext = (HANDLE)pContext; cleanup: if (pUsername != NULL) { gss_release_name((OM_uint32 *)&dwMinorStatus, &pUsername); } LWIO_SAFE_FREE_STRING(pszTargetName); LWIO_SAFE_FREE_STRING(pszServerName); LWIO_SAFE_FREE_STRING(pszUsername); LWIO_SAFE_FREE_STRING(pszDomain); LWIO_SAFE_FREE_STRING(pszPassword); return dwError; sec_error: dwError = LWIO_ERROR_GSS; error: *phSMBGSSContext = NULL; if (pContext) { SMBGSSContextFree(pContext); } goto cleanup; }
int main( int argc, char* argv[] ) { DWORD dwError = 0; PSTR pszHostName = NULL; PWSTR pwszHostName = NULL; PWSTR pwszCanonName = NULL; PSTR pszCanonName = NULL; PLWNET_RESOLVE_ADDR *ppAddressList = NULL; DWORD dwAddressListLen = 0; DWORD i = 0; CHAR ipAddressBuf[INET_ADDRSTRLEN]; PCSTR pszAddress = NULL; DWORD ipAddressLen = 0; DWORD ipAddrFamily = 0; PBYTE pIpAddr = NULL; lwnet_init_logging_to_file(LWNET_LOG_LEVEL_VERBOSE, TRUE, ""); ParseArgs(argc, argv); if (argc == 1) { printf("usage: %s hostname\n", argv[0]); return 0; } pszHostName = argv[1]; dwError = LwRtlWC16StringAllocateFromCString(&pwszHostName, pszHostName); BAIL_ON_LWNET_ERROR(dwError); dwError = LWNetResolveName( (PCWSTR) pwszHostName, &pwszCanonName, &ppAddressList, &dwAddressListLen); BAIL_ON_LWNET_ERROR(dwError); dwError = LwRtlCStringAllocateFromWC16String(&pszCanonName, pwszCanonName); BAIL_ON_LWNET_ERROR(dwError); for (i=0; i<dwAddressListLen; i++) { if (ppAddressList[i]->AddressType == LWNET_IP_ADDR_V4) { ipAddressLen = 4; ipAddrFamily = PF_INET; pIpAddr = ppAddressList[i]->Address.Ip4Addr; } else if (ppAddressList[i]->AddressType == LWNET_IP_ADDR_V6) { ipAddressLen = 16; ipAddrFamily = PF_INET6; pIpAddr = ppAddressList[i]->Address.Ip4Addr; } pszAddress = inet_ntop(ipAddrFamily, pIpAddr, ipAddressBuf, sizeof(ipAddressBuf)); if (pszAddress) { printf("IP Address = %s\n", pszAddress); } } printf("Responses = %d Host: '%s'\n", dwAddressListLen, pszCanonName); cleanup: LWNetResolveNameFree(pwszCanonName, ppAddressList, dwAddressListLen); LWNET_SAFE_FREE_MEMORY(pwszHostName); LWNET_SAFE_FREE_STRING(pszCanonName); return (dwError); error: if (dwError == ERROR_BAD_NET_NAME) { printf("LWNetResolveName() failed DNS/NetBIOS name resolution\n"); } else { LWNET_LOG_ERROR("Failed communication with likewise-netlogond. " "Error code [%d]\n", dwError); } goto cleanup; }