diff --git a/auth-passwd.c b/auth-passwd.c index 2293668..2e53b1b 100644 --- a/auth-passwd.c +++ b/auth-passwd.c @@ -41,13 +41,13 @@ #include "xmalloc.h" #endif -/* - * We support only client side kerberos on Windows. - */ + /* + * We support only client side kerberos on Windows. + */ #ifdef WIN32_FIXME - #undef GSSAPI - #undef KRB5 +#undef GSSAPI +#undef KRB5 #endif #include @@ -155,23 +155,23 @@ warn_expiry(Authctxt *authctxt, auth_session_t *as) #ifdef HAVE_LOGIN_CAP if (authctxt->valid) { pwwarntime = login_getcaptime(lc, "password-warn", TWO_WEEKS, - TWO_WEEKS); + TWO_WEEKS); acwarntime = login_getcaptime(lc, "expire-warn", TWO_WEEKS, - TWO_WEEKS); + TWO_WEEKS); } #endif if (pwtimeleft != 0 && pwtimeleft < pwwarntime) { daysleft = pwtimeleft / DAY + 1; snprintf(buf, sizeof(buf), - "Your password will expire in %lld day%s.\n", - daysleft, daysleft == 1 ? "" : "s"); + "Your password will expire in %lld day%s.\n", + daysleft, daysleft == 1 ? "" : "s"); buffer_append(&loginmsg, buf, strlen(buf)); } if (actimeleft != 0 && actimeleft < acwarntime) { daysleft = actimeleft / DAY + 1; snprintf(buf, sizeof(buf), - "Your account will expire in %lld day%s.\n", - daysleft, daysleft == 1 ? "" : "s"); + "Your account will expire in %lld day%s.\n", + daysleft, daysleft == 1 ? "" : "s"); buffer_append(&loginmsg, buf, strlen(buf)); } } @@ -184,7 +184,7 @@ sys_auth_passwd(Authctxt *authctxt, const char *password) static int expire_checked = 0; as = auth_usercheck(pw->pw_name, authctxt->style, "auth-ssh", - (char *)password); + (char *)password); if (as == NULL) return (0); if (auth_getstate(as) & AUTH_PWEXPIRED) { @@ -192,7 +192,8 @@ sys_auth_passwd(Authctxt *authctxt, const char *password) disable_forwarding(); authctxt->force_pwchange = 1; return (1); - } else { + } + else { if (!expire_checked) { expire_checked = 1; warn_expiry(authctxt, as); @@ -202,183 +203,43 @@ sys_auth_passwd(Authctxt *authctxt, const char *password) } #elif defined(WIN32_FIXME) +extern int auth_sock; int sys_auth_passwd(Authctxt *authctxt, const char *password) { - /* - * Authenticate on Windows - */ - - struct passwd *pw = authctxt -> pw; + /* + * Authenticate on Windows + */ - HANDLE hToken = INVALID_HANDLE_VALUE; - - BOOL worked = FALSE; - - LPWSTR user_UTF16 = NULL; - LPWSTR password_UTF16 = NULL; - LPWSTR domain_UTF16 = NULL; + { + u_char *blob = NULL; + size_t blen = 0; + DWORD token = 0; + struct sshbuf *msg = NULL; - int buffer_size = 0; - - /* - * Identify domain or local login. - */ + msg = sshbuf_new(); + if (!msg) + return 0; + if (sshbuf_put_u8(msg, 100) != 0 || + sshbuf_put_cstring(msg, "password") != 0 || + sshbuf_put_cstring(msg, authctxt->user) != 0 || + sshbuf_put_cstring(msg, password) != 0 || + ssh_request_reply(auth_sock, msg, msg) != 0 || + sshbuf_get_u32(msg, &token) != 0) { + debug("auth agent did not authorize client %s", authctxt->pw->pw_name); + return 0; + } - char *username = authctxt->user; - char *domainslash = strchr(authctxt->user, '\\'); - if (domainslash) { - // domain\username format - char *domainname = authctxt->user; - *domainslash = '\0'; - username = ++domainslash; // username is past the domain \ is the username + if (blob) + free(blob); + if (msg) + sshbuf_free(msg); - // Convert domainname from UTF-8 to UTF-16 - buffer_size = MultiByteToWideChar(CP_UTF8, 0, domainname, -1, NULL, 0); + authctxt->methoddata = token; + + } - if (buffer_size > 0) - { - domain_UTF16 = xmalloc(4 * buffer_size); - } - else - { - return 0; - } - - if (0 == MultiByteToWideChar(CP_UTF8, 0, domainname, - -1, domain_UTF16, buffer_size)) - { - free(domain_UTF16); - - return 0; - } - } - else if (domainslash = strchr(authctxt->user, '@')) { - // username@domain format - username = authctxt->user; - *domainslash = '\0'; - char *domainname = ++domainslash; // domainname is past the user@ - - // Convert domainname from UTF-8 to UTF-16 - buffer_size = MultiByteToWideChar(CP_UTF8, 0, domainname, -1, NULL, 0); - - if (buffer_size > 0) - { - domain_UTF16 = xmalloc(4 * buffer_size); - } - else - { - return 0; - } - - if (0 == MultiByteToWideChar(CP_UTF8, 0, domainname, - -1, domain_UTF16, buffer_size)) - { - free(domain_UTF16); - - return 0; - } - } - else { - domain_UTF16 = strchr(authctxt->user, '@') ? NULL : L"."; - } - - authctxt -> methoddata = hToken; - - if (domain_UTF16 == NULL) - { - debug3("Using domain logon..."); - } - - /* - * Convert username from UTF-8 to UTF-16 - */ - - buffer_size = MultiByteToWideChar(CP_UTF8, 0, username, -1, NULL, 0); - - if (buffer_size > 0) - { - user_UTF16 = xmalloc(4 * buffer_size); - } - else - { - return 0; - } - - if (0 == MultiByteToWideChar(CP_UTF8, 0, username, - -1, user_UTF16, buffer_size)) - { - free(user_UTF16); - - return 0; - } - - /* - * Convert password from UTF-8 to UTF-16 - */ - - buffer_size = MultiByteToWideChar(CP_UTF8, 0, password, -1, NULL, 0); - - if (buffer_size > 0) - { - password_UTF16 = xmalloc(4 * buffer_size); - } - else - { - return 0; - } - - if (0 == MultiByteToWideChar(CP_UTF8, 0, password, -1, - password_UTF16 , buffer_size)) - { - free(password_UTF16 ); - - return 0; - } - - worked = LogonUserW(user_UTF16, domain_UTF16, password_UTF16, - LOGON32_LOGON_NETWORK, - LOGON32_PROVIDER_DEFAULT, &hToken); - - - free(user_UTF16); - free(password_UTF16); - if (domainslash) free(domain_UTF16); - - /* - * If login still fails, go out. - */ - - if (!worked || hToken == INVALID_HANDLE_VALUE) - { - return 0; - } - - /* - * Make sure this can be inherited for when - * we start shells or commands. - */ - - worked = SetHandleInformation(hToken, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); - - if (!worked) - { - CloseHandle(hToken); - - hToken = INVALID_HANDLE_VALUE; - - authctxt -> methoddata = hToken; - - return 0; - } - - /* - * Save the handle (or invalid handle) as method-specific data. - */ - - authctxt -> methoddata = hToken; - - return 1; + return 1; } #elif !defined(CUSTOM_SYS_AUTH_PASSWD) @@ -397,13 +258,13 @@ sys_auth_passwd(Authctxt *authctxt, const char *password) /* Encrypt the candidate password using the proper salt. */ encrypted_password = xcrypt(password, - (pw_password[0] && pw_password[1]) ? pw_password : "xx"); + (pw_password[0] && pw_password[1]) ? pw_password : "xx"); /* * Authentication is accepted if the encrypted passwords * are identical. */ return encrypted_password != NULL && - strcmp(encrypted_password, pw_password) == 0; + strcmp(encrypted_password, pw_password) == 0; } #endif diff --git a/contrib/win32/win32compat/ssh-agent/authagent-request.c b/contrib/win32/win32compat/ssh-agent/authagent-request.c index f558054..a7db697 100644 --- a/contrib/win32/win32compat/ssh-agent/authagent-request.c +++ b/contrib/win32/win32compat/ssh-agent/authagent-request.c @@ -31,6 +31,7 @@ #define UMDF_USING_NTSTATUS #include +#include #include #include #include @@ -50,6 +51,53 @@ InitLsaString(LSA_STRING *lsa_string, const char *str) } } +static void +EnablePrivilege(const char *privName, int enabled) +{ + TOKEN_PRIVILEGES tp; + HANDLE hProcToken = NULL; + LUID luid; + + int exitCode = 1; + + if (LookupPrivilegeValueA(NULL, privName, &luid) == FALSE || + OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hProcToken) == FALSE) + goto done; + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = enabled ? SE_PRIVILEGE_ENABLED : 0; + + AdjustTokenPrivileges(hProcToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); + +done: + if (hProcToken) + CloseHandle(hProcToken); + + return; +} + + +void +LoadProfile(HANDLE token, char* user, char* domain) { + PROFILEINFOA profileInfo; + profileInfo.dwFlags = PI_NOUI; + profileInfo.lpProfilePath = NULL; + profileInfo.lpUserName = user; + profileInfo.lpDefaultPath = NULL; + profileInfo.lpServerName = domain; + profileInfo.lpPolicyPath = NULL; + profileInfo.hProfile = NULL; + profileInfo.dwSize = sizeof(profileInfo); + EnablePrivilege("SeBackupPrivilege", 1); + EnablePrivilege("SeRestorePrivilege", 1); + if (LoadUserProfileA(token, &profileInfo) == FALSE) + debug("Loading user profile failed ERROR: %d", GetLastError()); + EnablePrivilege("SeBackupPrivilege", 0); + EnablePrivilege("SeRestorePrivilege", 0); + +} + #define MAX_USER_LEN 256 static HANDLE generate_user_token(wchar_t* user) { @@ -167,9 +215,67 @@ done: return token; } -#define AUTH_REQUEST "pubkey" +#define PUBKEY_AUTH_REQUEST "pubkey" +#define PASSWD_AUTH_REQUEST "password" #define MAX_USER_NAME_LEN 256 +int process_passwordauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) { + char *user = NULL, *pwd = NULL, *dom = NULL, *tmp; + //wchar_t *userW = NULL, *domW = NULL, *pwdW = NULL; + size_t user_len = 0, pwd_len = 0, dom_len = 0; + int r = -1; + HANDLE token = 0, dup_token, client_proc = 0; + ULONG client_pid; + + if (sshbuf_get_cstring(request, &user, &user_len) != 0 || + sshbuf_get_cstring(request, &pwd, &pwd_len) != 0 || + user_len == 0 || + pwd_len == 0 ){ + debug("bad password auth request"); + goto done; + } + + /*TODO - support Unicode*/ + + if ((tmp = strchr(user, '\\')) != NULL) { + dom = user; + user = tmp + 1; + *tmp = '\0'; + + } + else if ((tmp = strchr(user, '@')) != NULL) { + dom = tmp + 1; + *tmp = '\0'; + } + + if (LogonUser(user, dom, pwd, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &token) == FALSE || + (FALSE == GetNamedPipeClientProcessId(con->connection, &client_pid)) || + ((client_proc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, client_pid)) == NULL) || + (FALSE == DuplicateHandle(GetCurrentProcess(), token, client_proc, &dup_token, TOKEN_QUERY | TOKEN_IMPERSONATE, FALSE, DUPLICATE_SAME_ACCESS)) || + (sshbuf_put_u32(response, dup_token) != 0)) { + debug("failed to authenticate user"); + goto done; + } + + LoadProfile(token, user, dom); + r = 0; +done: + /* TODO Fix this hacky protocol*/ + if ((r == -1) && (sshbuf_put_u8(response, SSH_AGENT_FAILURE) == 0)) + r = 0; + + if (user) + free(user); + if (pwd) + free(pwd); + if (token) + CloseHandle(token); + if (client_proc) + CloseHandle(client_proc); + + return r; +} + int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response, struct agent_connection* con) { int r = -1; char *key_blob, *user, *sig, *blob; @@ -214,7 +320,22 @@ int process_pubkeyauth_request(struct sshbuf* request, struct sshbuf* response, debug("failed to authorize user"); goto done; } - + { + /*TODO - support Unicode*/ + char *tmp, *u = user, *d = NULL; + if ((tmp = strchr(user, '\\')) != NULL) { + d = user; + u = tmp + 1; + *tmp = '\0'; + + } + else if ((tmp = strchr(user, '@')) != NULL) { + d = tmp + 1; + *tmp = '\0'; + } + LoadProfile(token, u, d); + } + r = 0; done: if (user) @@ -238,8 +359,10 @@ int process_authagent_request(struct sshbuf* request, struct sshbuf* response, s return -1; } - if (opn_len == strlen(AUTH_REQUEST) && memcmp(opn, AUTH_REQUEST, opn_len) == 0) + if (opn_len == strlen(PUBKEY_AUTH_REQUEST) && memcmp(opn, PUBKEY_AUTH_REQUEST, opn_len) == 0) return process_pubkeyauth_request(request, response, con); + else if (opn_len == strlen(PASSWD_AUTH_REQUEST) && memcmp(opn, PASSWD_AUTH_REQUEST, opn_len) == 0) + return process_passwordauth_request(request, response, con); else { debug("unknown auth request: %s", opn); return -1;