41
41
#include <sys/types.h>
42
42
43
43
#include <pwd.h>
44
- #ifdef WINDOWS
45
- #include <logonuser.h>
46
- #endif
47
44
#include <stdio.h>
48
45
#include <string.h>
49
46
#include <stdarg.h>
59
56
#include "auth-options.h"
60
57
#include "authfd.h"
61
58
59
+ #ifdef WINDOWS
60
+ #include "logonuser.h"
61
+ #include "monitor_wrap.h"
62
+ #endif
63
+
62
64
extern Buffer loginmsg ;
63
65
extern ServerOptions options ;
64
66
@@ -228,10 +230,53 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
228
230
}
229
231
230
232
#elif defined(WINDOWS )
233
+ HANDLE password_auth_token = NULL ;
234
+ HANDLE process_custom_lsa_auth (char * , const char * , char * );
235
+
236
+ void
237
+ sys_auth_passwd_lsa (Authctxt * authctxt , const char * password )
238
+ {
239
+ char * lsa_auth_pkg = NULL ;
240
+ wchar_t * lsa_auth_pkg_w = NULL ;
241
+ int domain_len = 0 , lsa_auth_pkg_len = 0 ;
242
+ HKEY reg_key = 0 ;
243
+ REGSAM mask = STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY ;
244
+
245
+ if ((RegOpenKeyExW (HKEY_LOCAL_MACHINE , L"SOFTWARE\\OpenSSH" , 0 , mask , & reg_key ) == ERROR_SUCCESS ) &&
246
+ (RegQueryValueExW (reg_key , L"LSAAuthenticationPackage" , 0 , NULL , NULL , & lsa_auth_pkg_len ) == ERROR_SUCCESS )) {
247
+ lsa_auth_pkg_w = (wchar_t * ) malloc (lsa_auth_pkg_len ); // lsa_auth_pkg_len includes the null terminating character.
248
+ if (!lsa_auth_pkg_w )
249
+ fatal ("%s: out of memory" , __func__ );
250
+
251
+ memset (lsa_auth_pkg_w , 0 , lsa_auth_pkg_len );
252
+ if (RegQueryValueExW (reg_key , L"LSAAuthenticationPackage" , 0 , NULL , (LPBYTE )lsa_auth_pkg_w , & lsa_auth_pkg_len ) == ERROR_SUCCESS ) {
253
+ lsa_auth_pkg = utf16_to_utf8 (lsa_auth_pkg_w );
254
+ if (!lsa_auth_pkg )
255
+ fatal ("utf16_to_utf8 failed to convert lsa_auth_pkg_w:%ls" , lsa_auth_pkg_w );
256
+
257
+ debug ("Authenticating using LSA Auth Package:%ls" , lsa_auth_pkg_w );
258
+ password_auth_token = process_custom_lsa_auth (authctxt -> pw -> pw_name , password , lsa_auth_pkg );
259
+ }
260
+ }
261
+
262
+ done :
263
+ if (lsa_auth_pkg_w )
264
+ free (lsa_auth_pkg_w );
265
+
266
+ if (lsa_auth_pkg )
267
+ free (lsa_auth_pkg );
268
+
269
+ if (reg_key )
270
+ RegCloseKey (reg_key );
271
+ }
272
+
231
273
/*
232
- * Authenticate on Windows - Call LogonUser and retrieve user token
274
+ * Authenticate on Windows
275
+ * - Call LogonUser and retrieve user token
276
+ * - If LogonUser fails, then try the LSA (Local Security Authority) authentication.
233
277
*/
234
- int sys_auth_passwd (Authctxt * authctxt , const char * password )
278
+ int
279
+ sys_auth_passwd (Authctxt * authctxt , const char * password )
235
280
{
236
281
wchar_t * user_utf16 = NULL , * udom_utf16 = NULL , * pwd_utf16 = NULL , * tmp ;
237
282
HANDLE token = NULL ;
@@ -249,25 +294,33 @@ int sys_auth_passwd(Authctxt *authctxt, const char *password)
249
294
}
250
295
251
296
if (LogonUserExExWHelper (user_utf16 , udom_utf16 , pwd_utf16 , LOGON32_LOGON_NETWORK_CLEARTEXT ,
252
- LOGON32_PROVIDER_DEFAULT , NULL , & token , NULL , NULL , NULL , NULL ) == FALSE) {
253
- if (GetLastError () == ERROR_PASSWORD_MUST_CHANGE )
254
- /*
255
- * TODO - need to add support to force password change
256
- * by sending back SSH_MSG_USERAUTH_PASSWD_CHANGEREQ
257
- */
297
+ LOGON32_PROVIDER_DEFAULT , NULL , & token , NULL , NULL , NULL , NULL ) == TRUE)
298
+ password_auth_token = token ;
299
+ else {
300
+ if (GetLastError () == ERROR_PASSWORD_MUST_CHANGE )
301
+ /*
302
+ * TODO - need to add support to force password change
303
+ * by sending back SSH_MSG_USERAUTH_PASSWD_CHANGEREQ
304
+ */
258
305
error ("password for user %s has expired" , authctxt -> pw -> pw_name );
259
- else
260
- debug ("failed to logon user: %ls domain: %ls error:%d" , user_utf16 , udom_utf16 , GetLastError ());
261
- goto done ;
262
- }
306
+ else {
307
+ debug ("Windows authentication failed for user: %ls domain: %ls error:%d" , user_utf16 , udom_utf16 , GetLastError ());
263
308
264
- authctxt -> auth_token = (void * )(INT_PTR )token ;
265
- r = 1 ;
309
+ /* If LSA authentication package is configured then it will return the auth_token */
310
+ sys_auth_passwd_lsa (authctxt , password );
311
+ }
312
+ }
313
+
266
314
done :
315
+ if (password_auth_token )
316
+ r = 1 ;
317
+
267
318
if (user_utf16 )
268
319
free (user_utf16 );
320
+
269
321
if (pwd_utf16 )
270
322
SecureZeroMemory (pwd_utf16 , sizeof (wchar_t ) * wcslen (pwd_utf16 ));
323
+
271
324
return r ;
272
325
}
273
326
#endif /* WINDOWS */
0 commit comments