Locating package NTLM ...Package not found

Hello all, we cannot seem to call NTLMSetUserInfo to setup user accounts for Telnet and FTP Servers running under WEC7. We get error code:6 from GetLastError() and the call fails to set a user account.

We are using the Colibri T30 running WEC7 BSP 2.3 in our instruments. I built an image based on the 2.3 OS Design. I was sure to include the SYSGEN_AUTH_NTLM and of course SYSGEN_TELNETD and SYSGEN_FTPD. Our little program to setup the user accounts seems to find the ntlmssp.dll, it prints out
“Load module: ntlmssp.dll” , before it prints out “SECUR32: Locating package ‘NTLM’ …Package NOT found.”

We are able to login to Ftp anonymously fine (by setting the registry settings for allow anonymous and allow anonymous upload). But telnet displays “locating package ‘NTLM’ package NOT found” to the debug message buffer when we try and authenticate.

I also check and tried the advice from this FTP password in image - #2 by samuel.tx - Technical Support - Toradex Community answer here.

We are thouroughly confused here. Please help.

Brad

Dear @bertin,

Our default standard release image having SYSGEN_FTPD, SYSGEN_TELNETD, and SYSGEN_AUTH_NTLM. So, you don’t need to build an image for that.

NTLMSetUserInfo(L"admin", L"admin"); API is works with our standard release image. We included following dependencies for that

BOOL NTLMSetUserInfo(
  LPTSTR pszUser,
  LPTSTR pszPassword
);
#pragma comment(lib, "ntlmssp")

Could you share your issue reproducible application project with us, it will help us to look at the issue very specifically and solve it quickly.

Thank you

So I compiled used the 2.3 OSDesign and 2.3 BSP from toradex and built the solution and got a working image from that.

I checked my software containing NTLMSetUserInfo, which I will post below, and it indicates that the function call worked and I can see some kind of entry (it is a blob) posted in the registry which shows the username I just added. So I guess it worked. I was not able to telnet into a T30 running the new image…not sure why. But I will assume that the user was setup ok.

The same software doesn’t work on our image.
I checked the ce.bib and ceconfig.h for the output of our image that we have done a checked sysgen and image for.

From the ce.bib here are the entries:

; @CESYSGEN IF CE_MODULES_NTLMSSP   
ntlmssp.dll     D:\Windows_Compact_7\OSDesigns\ColibriTegra_Core\RelDir\NVAP_ARMV7_Checked\ntlmssp.dll       NK  SH    
ntlmssp_svc.dll D:\Windows_Compact_7\OSDesigns\ColibriTegra_Core\RelDir\NVAP_ARMV7_Checked\ntlmssp_svc.dll   NK  SH 
; @CESYSGEN ENDIF

; @CESYSGEN IF SERVERS_MODULES_TELNETD
telnetd.dll     D:\Windows_Compact_7\OSDesigns\ColibriTegra_Core\RelDir\NVAP_ARMV7_Checked\telnetd.dll       NK  SH
; @CESYSGEN ENDIF 
; @CESYSGEN
IF SERVERS_MODULES_FTPD    
ftpd.dll        D:\Windows_Compact_7\OSDesigns\ColibriTegra_Core\RelDir\NVAP_ARMV7_Checked\ftpd.dll          NK  SH
; @CESYSGEN ENDIF

from the ceconfig.h

#define CE_MODULES_NTLMSSP 1
#define CE_MODULES_NTLMSSP_SVC 1

#define SERVERS_MODULES_TELNETD 1
#define SERVERS_MODULES_FTPD 1

Here is the function I created to verify that the system could use NTLM and to add a user via NTLMSetUserInfo

BOOL SetupUserAccount(LPTSTR username,LPTSTR password){ 	
  BOOL result = FALSE;
  
  TCHAR nameBuffer[512]; 	ULONG nameSize = 512;
  
  SEC_WINNT_AUTH_IDENTITY AdditionalCredentials; 
  SECURITY_STATUS status;  	
  CredHandle hCredential;  	
  TimeStamp tsExpiry; 
  BOOL bSupplyCredentials; 
  
  // Zero memory 
  memset(&AdditionalCredentials,0,sizeof(SEC_WINNT_AUTH_IDENTITY));
  
  // If there are additional credentials stored in lpszUserName,  
  // lpszDomainName, and lpszPassword, fill them in here. 
  AdditionalCredentials.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; 
  
  status = AcquireCredentialsHandle ( 
  	NULL,                   // No principal name  		
      TEXT("NTLM"),           // Package name 
  	SECPKG_CRED_OUTBOUND,   // Credential use flag  		
      NULL,                   // No logon identifier 
  	bSupplyCredentials ? &AdditionalCredentials : NULL, //Package-specific data       		
      NULL,                   // No GetKey function  		
      NULL,                   // No GetKey function argument 
  	&hCredential,           // Receives the new credential  		
      &tsExpiry);             // Receives the expiration   	
  if(NTLMSetUserInfo(username,password)== TRUE){ 		
      RETAILMSG(1,(_T("set the password for %s\n"),username)); 		
      LONG flushRes = RegFlushKey(HKEY_LOCAL_MACHINE);
      if(flushRes != ERROR_SUCCESS){
          RETAILMSG(1,(_T("Failed to flush HKLM with code:%x\n"),flushRes));
          return FALSE; } 		
      flushRes = RegFlushKey(HKEY_CURRENT_USER);
      if(flushRes != ERROR_SUCCESS){
          RETAILMSG(1,(_T("Failed to flush HKCU with code:%x\n"),flushRes));
          return FALSE; } 		
      result = TRUE;
  }else{ 		
      RETAILMSG(1,(_T("failed to set the password for ADMIN\n")));
      DWORD err = GetLastError();
      RETAILMSG(1,(_T("Failed with error:%x\n"),err)); 	}
  
  return result; }

Here is the trace output from my programming running on our image, which doesn’t work

SECUR32: Loading package DLL:
'ntlmssp.dll'. SECUR32: Loading
package DLL: 'kerberos.dll'. Load
module: kerberos.dll Load module:
cryptdll.dll Load module: ws2.dll Load
module: ssllsp.dll Load module:
wspm.dll SECUR32: Loading package DLL:
'spnego.dll'. Load module: spnego.dll
SECUR32: Loading package DLL:
'credssp.dll'. SECUR32: Package [1]
loaded -- 'Microsoft Unified Security
Protocol Provider' SECUR32: Package
[2] loaded -- 'Microsoft TLS 1.0'
SECUR32: Package [3] loaded --
'Microsoft SSL 3.0' SECUR32: Package
[4] loaded -- 'Microsoft SSL 2.0'
SECUR32: Package [5] loaded --
'Kerberos' SECUR32: Package [6] loaded
-- 'Negotiate' SECUR32: Locating package 'NTLM' ...Package NOT found.
failed to set the password for ADMIN
Failed with error:6

Here is the output from a working image (which shows no output from secur32, why?)

set the password for ADMIN admin was
setup ok

Thoroughly confused here, no idea about the differences in output for why one does and does not work.

Hi Raja, I have another question here.

I compared the .pbxml files from the OSDesign that you offer (version 2.3-20190702) our .pbxml file from our project where that we based off your OSDesign and manually selected the SYSGEN_AUTH_NTLM catalog item.

How are you including ntlm support in your OSDesign? I can’t see where you have selected the item. I know we have selected the item in our OSDesign and I verified the presence of the file in our flatrelease directory.

I have even changed our code to the following

BOOL (*_NTLMSetUserInfo)(LPTSTR pszUser, LPTSTR pszPassword);

BOOL SetUserInfoFromLib(LPTSTR user,LPTSTR pass){
    BOOL bRetVal = 0;
    DWORD dwLastErr = 0;
    HINSTANCE hLib = LoadLibrary(_T("ntlmssp.dll"));

    if (!hLib)
            return -1;

    _NTLMSetUserInfo =
        (BOOL(*)(LPTSTR pszUser, LPTSTR pszPassword))
        GetProcAddress(hLib, _T("NTLMSetUserInfo")); 

    if (_NTLMSetUserInfo)
            bRetVal = _NTLMSetUserInfo(user, pass);

    if (!bRetVal)
    {
        dwLastErr = GetLastError();
        RETAILMSG(TRUE, (_T("Error occured | Last error: %d\r\n"), dwLastErr));
    }

    _NTLMSetUserInfo = NULL;
    FreeLibrary(hLib);

    return bRetVal; }

This code loads the library and returns an address from GetProcAddress (probably need to verify that it is the correct address in a link map) but still returns an error code 6 on our image, indicating an invalid handle (I guess?)

What is going on here?

// AddUserAccounts.cpp : Defines the entry point for the application.
//

#include "stdafx.h"

BOOL (*_NTLMSetUserInfo)(LPTSTR pszUser, LPTSTR pszPassword);
BOOL(*_NTLMEnumUser)(DWORD index,LPTSTR pszUser,LPDWORD pcchUser);
BOOL (*_NTLMGetGroupList)(  WCHAR* userName,  WCHAR* groupList,  DWORD* pdwccLen);

BOOL SetUserInfo(LPTSTR user,LPTSTR pass){
  BOOL bRetVal = 0;
  DWORD dwLastErr = 0;

  HINSTANCE hLib = LoadLibrary(_T("ntlmssp.dll"));
  
  if (!hLib)
          return -1;

  _NTLMSetUserInfo =
          (BOOL(*)(LPTSTR pszUser, LPTSTR pszPassword))
          GetProcAddress(hLib, _T("NTLMSetUserInfo"));
  _NTLMEnumUser = (BOOL(*)(DWORD index,LPTSTR pszUser,LPDWORD pcchUser))
          GetProcAddress(hLib, _T("NTLMEnumUser"));
  _NTLMGetGroupList = (BOOL (*)(  WCHAR* userName,  WCHAR* groupList,  DWORD* pdwccLen))
      GetProcAddress(hLib,_T("NTLMGetGroupList"));
  if(_NTLMGetGroupList){
      TCHAR groupBuffer[256] = {0};
      DWORD lenGroup = 256;
      BOOL res = _NTLMGetGroupList(user,groupBuffer,&lenGroup);

      if(res)
          RETAILMSG(TRUE, (_T("Group list:%s"),groupBuffer));
      
  }

  if(_NTLMEnumUser){
      TCHAR buffer[256] = {0};
      DWORD len = 256;
      for(DWORD i = 0;i < 5;i++){
          BOOL succeeded = _NTLMEnumUser(i,buffer,&len);
          if(!succeeded){
              RETAILMSG(TRUE, (_T("Mod No user found at %d\r\n"),i));
          }else{
              RETAILMSG(TRUE, (_T("Mod found user named %s\r\n"),buffer));
          }
          len = 256;
      }
  }
  if (_NTLMSetUserInfo)
          bRetVal = _NTLMSetUserInfo(user, pass);

  if (!bRetVal)
  {
          dwLastErr = GetLastError();
          RETAILMSG(TRUE, (_T("Error occured | Last error: %d\r\n"), dwLastErr));
  }

  _NTLMSetUserInfo = NULL;
  FreeLibrary(hLib);

  return bRetVal;
}

int WINAPI WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR     lpCmdLine,
                     int       nCmdShow)
{
  TCHAR username[128] = {0};
  _stprintf(username,L"ADMIN");
  TCHAR password[128] = {0};
  _stprintf(password,L"12345");

  if(SetUserInfo(username,password) == TRUE)
      {
          //RETAILMSG(1,(_T("admin was setup ok")));
          //MessageBox(hWnd,(_T("%s was setup ok"),username),L"adding user",MB_OK);
          RETAILMSG(1,(_T("user account: %s, suceeded"),username));
      }else{
          //MessageBox(hWnd,(_T("%s was setup ok"),username),L"error adding user",MB_OK);
          RETAILMSG(1,(_T("user account: %s, failed"),username));
      }

  TCHAR userConfigName[128] = {0};
  _stprintf(userConfigName,L"USERCONFIG");
  TCHAR userConfigPassword[128] = {0};
  _stprintf(userConfigPassword,L"12345");

  if(SetUserInfo(userConfigName,userConfigPassword) == TRUE)
      {
          //RETAILMSG(1,(_T("admin was setup ok")));
          //MessageBox(hWnd,(_T("%s was setup ok"),username),L"adding user",MB_OK);
          RETAILMSG(1,(_T("user account: %s, suceeded"),userConfigName));
      }else{
          //MessageBox(hWnd,(_T("%s was setup ok"),username),L"error adding user",MB_OK);
          RETAILMSG(1,(_T("user account: %s, failed"),userConfigName));
      }

      TCHAR userDataName[128] = {0};
  _stprintf(userDataName,L"USERDATA");
  TCHAR userDataPassword[128] = {0};
  _stprintf(userDataPassword,L"12345");

  if(SetUserInfo(userDataName,userDataPassword) == TRUE)
      {
          //RETAILMSG(1,(_T("admin was setup ok")));
          //MessageBox(hWnd,(_T("%s was setup ok"),username),L"adding user",MB_OK);
          RETAILMSG(1,(_T("user account: %s, suceeded"),userDataName));
      }else{
          //MessageBox(hWnd,(_T("%s was setup ok"),username),L"error adding user",MB_OK);
          RETAILMSG(1,(_T("user account: %s, failed"),userDataName));
      }
  return 0;
}

This is the complete source file

Hi Raja,

We have found that adding vpn support to our image, like outlined here

is what is leading to our problems with setting up user accounts with ntlm.

And vpn isn’t working either, so it seems that adding the components to enable the vpn actually break more than they fix.

I created an entirely new os design based again on the Toradex OSDesign and was able to verify step by step where the NTLM problem happened… and it happened with a sysgen after the vpn catalog items were added.

So it should be easy to reproduce what the problem is. Using the OSDesign 2.3 and BSP 2.3 1) add the vpn catalog items from your instructions and 2) add this registry bit to the OSDesign.reg Update: Sie können keine L2TP/IPSec-Server hinter einem NAT-T-Gerät in Windows Embedded Compact 7 herstellen - Microsoft-Support

Please let me know if you can reproduce the problem.

Thanks,

Brad

Dear @bertin,

I build an image with components you suggested and I can able to run the SetUserInfo application, please find the log here.

I uploaded the built image, ce.bib and regedit.ini and ceconfig.h file for your reference. Could you share similar files of yours?

Until which update did you install on your PC. I have tested with till December 2017 updates.
v2.3 image released with March 2019 updates.

So, could you apply the March 2019 or latest updates and build the custom image and test again.

SYSGEN_AUTH_NTLM was added due to the dependency of File Server(SMB/CIFS) and File Server customizable WebUI.We didn’t manually select that component.

Hi Raja,

Thanks for trying that. Ok now NTLM is working… specifically I have found that when this item, “SYSGEN_CERTS :- Cryptography API: Next Generation (CNG) Key Storage and Retrieval”, is added, the NTLM breaks. Removing that item (removing explicitly adding that component from by checking on that) is what seems to Did you try the VPN on that image? Because I loaded that image on our dev board here and wasn’t able to setup VPN with L2TP… So either I seem to have NTLM working or NTLM and VPN broken.

I attached our ce.bib,config.h, and reginit.ini as well as an image of our items selected in catalog.
link text

I just crosschecked our software and settings on an older OS based on Toradex OS Design
2.0 06 June 2018

Our communication settings and software with VPN on your older image. This is the same software that I just tested against the new 2.3 based design.

So there is most definetely a problem here with the newer OS.

Thank you for the feedback. As discussed on the phone, I will close this ticket.

Regards, Andy