Subversion Repositories Aucun

Rev

Rev 223 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
114 ixe013 1
/*
2
 Copyright (c) 2008, Guillaume Seguin ([email protected])
3
 All rights reserved.
4
 
5
 Redistribution and use in source and binary forms, with or without
6
 modification, are permitted provided that the following conditions
7
 are met:
8
 
9
 1. Redistributions of source code must retain the above copyright
10
    notice, this list of conditions and the following disclaimer.
11
 
12
 2. Redistributions in binary form must reproduce the above copyright
13
    notice, this list of conditions and the following disclaimer in the
14
    documentation and/or other materials provided with the distribution.
15
 
16
 THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
17
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
20
 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 SUCH DAMAGE.
27
*/
28
 
112 ixe013 29
#include <windows.h>
138 ixe013 30
#include <wincrypt.h>
112 ixe013 31
#include "loggedout_dlg.h"
32
#include "dlgdefs.h"
33
#include "trace.h"
114 ixe013 34
#include "settings.h"
137 ixe013 35
#include "global.h"
112 ixe013 36
 
114 ixe013 37
#define _SECURE_ATL 1
38
 
39
#include <atlbase.h>
224 ixe013 40
#include <atlapp.h>
41
#include <atlctrls.h>
114 ixe013 42
#include "StaticPrompt.h"
43
 
138 ixe013 44
#include "randpasswd.h"
162 ixe013 45
#include "securityhelper.h"
121 ixe013 46
 
138 ixe013 47
 
137 ixe013 48
wchar_t gUsername[512] = L"";
215 ixe013 49
size_t gUsername_len = sizeof gUsername / sizeof * gUsername;
121 ixe013 50
 
164 ixe013 51
//We want a long password (16 chars) that changes at every boot
52
//But we also need a beacon (5 chars) to know if its a left over password
53
//from a previous boot.
54
const wchar_t gEncryptedTag[] = L"AUCUN";
215 ixe013 55
const size_t gEncryptedTag_len = sizeof gEncryptedTag / sizeof * gEncryptedTag;
164 ixe013 56
#define TAGGED_AUCUN_PWLEN (AUCUN_PWLEN+gEncryptedTag_len)
57
//And the buffer must be multiple of the  block size (I guess)
215 ixe013 58
wchar_t gEncryptedRandomSelfservePassword[CRYPTPROTECTMEMORY_BLOCK_SIZE * (((TAGGED_AUCUN_PWLEN - 1) / CRYPTPROTECTMEMORY_BLOCK_SIZE) + 1)] = L"";
221 ixe013 59
const DWORD gEncryptedRandomSelfservePassword_len = CRYPTPROTECTMEMORY_BLOCK_SIZE * (((TAGGED_AUCUN_PWLEN - 1) / CRYPTPROTECTMEMORY_BLOCK_SIZE) + 1);
164 ixe013 60
 
114 ixe013 61
static CStaticPromptCtrl gStaticPrompt;
62
 
63
enum
64
{
215 ixe013 65
    IDC_SELFSERVE_FIRST = 1000,
66
    IDC_SELFSERVEPROMPT
114 ixe013 67
};
68
 
116 ixe013 69
//Moves a control in a dialog
113 ixe013 70
void MoveControl(HWND hwndDlg, int id, int xoffset, int yoffset)
71
{
215 ixe013 72
    HWND control = GetDlgItem(hwndDlg, id);
73
    RECT rect;
74
    //Move the bottom row controls (Ok, Cancel, Options, etc.)
75
    GetWindowRect(control, &rect);
76
    POINT p;
77
    p.x = rect.left;
78
    p.y = rect.top;
79
    ScreenToClient(hwndDlg, &p);
80
    MoveWindow(control, p.x + xoffset, p.y + yoffset, rect.right - rect.left, rect.bottom - rect.top, TRUE);
113 ixe013 81
}
82
 
122 ixe013 83
// Gets the margin between the control and the parent's window border
121 ixe013 84
int GetDialogLeftMargin(HWND hwndDlg, int control)
85
{
215 ixe013 86
    RECT rect;
87
    POINT p;
88
    //As far left as the static controls
89
    GetWindowRect(GetDlgItem(hwndDlg, control), &rect);
90
    p.x = rect.left;
91
    p.y = rect.top;
92
    ScreenToClient(hwndDlg, &p);
93
    return p.x;
121 ixe013 94
}
95
 
96
 
122 ixe013 97
// Add a static control under between the password field and the ok button
116 ixe013 98
HWND AddStaticPrompt(HWND hwndDlg)
112 ixe013 99
{
215 ixe013 100
    HWND hwndPrompt = 0;
101
    wchar_t prompt[2048];
112 ixe013 102
 
215 ixe013 103
    if (GetSelfServeSetting(L"Text", prompt, sizeof prompt / sizeof * prompt) == S_OK)
104
    {
105
        RECT rect;
106
        POINT p;
107
        int increase = 0;
108
        int margin =  GetDialogLeftMargin(hwndDlg, 1506); //Username label
109
        //On the same line as the ok buttons (they will be moved)
110
        GetWindowRect(GetDlgItem(hwndDlg, IDOK), &rect);
111
        p.x = rect.left;
112
        p.y = rect.top;
113
        //As far right as the Option button
114
        GetWindowRect(GetDlgItem(hwndDlg, 1514), &rect);
115
        //As far left as the Ok button
116
        rect.left = p.x;
117
        //Here, rect contains the outer rectangle including all buttons from the bottom row
118
        //rect = left, top and bottom of IDOK,   right of 1514 (options);
119
        //Now convert the top-left coordinate in client for CreateWindow
120
        ScreenToClient(hwndDlg, &p);
121
        //We have the top left corner and the width. Let's create the dialog so we can
122
        //compute the height of the text
123
        hwndPrompt = CreateWindowEx(0, L"STATIC", InterpretCarriageReturn(prompt), SS_LEFT | SS_NOTIFY | WS_CHILD, //|WS_VISIBLE,
124
                                    p.x, p.y, rect.right - rect.left, 100, hwndDlg, (HMENU)IDC_SELFSERVEPROMPT, 0, 0);
125
        gStaticPrompt.SubclassWindow(hwndPrompt);
126
        increase = gStaticPrompt.ComputeRequiredHeight();
127
        gStaticPrompt.MoveWindow(p.x, p.y, rect.right - rect.left, increase);
128
        //Get the original window's dimension
129
        GetWindowRect(hwndDlg, &rect);
130
        //Make it bigger
131
        SetWindowPos(hwndDlg, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top + increase + margin, SWP_NOMOVE | SWP_NOZORDER);
132
        //Move the bottom row controls (Ok, Cancel, Options, etc.)
133
        MoveControl(hwndDlg, 24064, 0, increase + margin); //Bitmap (shows current keyboard layout)
134
        MoveControl(hwndDlg, IDOK, 0, increase + margin); //OK button
135
        MoveControl(hwndDlg, IDCANCEL, 0, increase + margin); //Cancel button
136
        MoveControl(hwndDlg, 1501, 0, increase + margin); //Shutdown button
137
        MoveControl(hwndDlg, 1514, 0, increase + margin); //Option button
138
        AnimateWindow(hwndPrompt, 200, AW_VER_POSITIVE | AW_SLIDE);
139
    }
112 ixe013 140
 
215 ixe013 141
    return hwndPrompt;
116 ixe013 142
}
143
 
122 ixe013 144
 
116 ixe013 145
INT_PTR CALLBACK MyWlxWkstaLoggedOutSASDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
146
{
215 ixe013 147
    static HWND hwndPrompt = 0;
148
    static int password_chances = -1;
149
    bool handled = false;
223 ixe013 150
    static bool domain_was_present = false;
215 ixe013 151
    INT_PTR result = 0;
116 ixe013 152
 
215 ixe013 153
    switch (uMsg)
154
    {
155
        case WM_INITDIALOG :
156
            {
157
                wchar_t buf[32];
217 ixe013 158
 
159
                DialogLParamHook* myinitparam = (DialogLParamHook*)lParam;
223 ixe013 160
                lParam = myinitparam->HookedLPARAM;                          
217 ixe013 161
 
162
                result = gDialogsProc[LOGGED_OUT_SAS_dlg].originalproc(hwndDlg, uMsg, wParam, lParam);
215 ixe013 163
                handled = true;
122 ixe013 164
 
223 ixe013 165
                domain_was_present = IsWindowVisible(GetDlgItem(hwndDlg, 1504)) == TRUE;
166
 
215 ixe013 167
                if(pgAucunContext->mLogonScenario == eAutoLogon)
168
                {
169
                    SetDlgItemText(hwndDlg, 1502, gUsername);
170
                    SetDlgItemText(hwndDlg, 1503, gEncryptedRandomSelfservePassword);
171
 
172
                    //TODO : wipe gEncryptedRandomSelfservePassword
173
 
174
                    //Click on OK for the user
175
                    PostMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDOK, 0), 0);
176
                }
177
                else if(*gEncryptedRandomSelfservePassword
178
                        && (GetSelfServeSetting(L"Attemps", buf, sizeof buf / sizeof * buf) == S_OK))
179
                {
180
                    password_chances = _wtoi(buf);
122 ixe013 181
 
215 ixe013 182
                    if (password_chances > 16)   //Some hardcoded limit to 16
183
                    {
184
                        password_chances = 3;
185
                    }
186
                    else if(password_chances == 0)
187
                    {
188
                        hwndPrompt = AddStaticPrompt(hwndDlg);    //Add the prompt right away
189
                    }
190
                }
191
                else
192
                {
193
                    password_chances = -1;
194
                }
195
            }
196
            break;
197
        case WM_COMMAND :
123 ixe013 198
 
223 ixe013 199
            if ((HIWORD(wParam) == STN_CLICKED) && (LOWORD(wParam) == IDC_SELFSERVEPROMPT))
215 ixe013 200
            {
201
                RECT rect;
202
                wchar_t username[255];
203
                int decrease;
204
                int margin =  GetDialogLeftMargin(hwndDlg, 1506); //Username label
205
                gStaticPrompt.GetWindowRect(&rect);
206
                decrease = rect.bottom - rect.top;
207
                gStaticPrompt.ShowWindow(SW_HIDE);
208
                //AnimateWindow(hwndPrompt, 200, AW_VER_NEGATIVE|AW_SLIDE|AW_HIDE);
209
                //Move the bottom row controls (Ok, Cancel, Options, etc.)
210
                MoveControl(hwndDlg, 24064, 0, -decrease - margin); //Bitmap (shows current keyboard layout)
211
                MoveControl(hwndDlg, IDOK, 0, -decrease - margin); //OK button
212
                MoveControl(hwndDlg, IDCANCEL, 0, -decrease - margin); //Cancel button
213
                MoveControl(hwndDlg, 1501, 0, -decrease - margin); //Shutdown button
214
                MoveControl(hwndDlg, 1514, 0, -decrease - margin); //Option button
215
                GetWindowRect(hwndDlg, &rect);
216
                SetWindowPos(hwndDlg, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top - decrease - margin, SWP_NOMOVE | SWP_FRAMECHANGED);
217
                //Save the username that user tried to logon
218
                GetDlgItemText(hwndDlg, 1502, gUsername, (int)gUsername_len);
219
                //TODO : Provide a safe default if registry is misconfigured
220
                GetSelfServeSetting(L"Username", username, sizeof username / sizeof * username);
221
                TRACE(eERROR, L"Switching to selfservice user %s\n", username);
222
                ShowWindow(GetDlgItem(hwndDlg, 1502), SW_HIDE); //Username
223
                ShowWindow(GetDlgItem(hwndDlg, 1503), SW_HIDE); //Password
224
                ShowWindow(GetDlgItem(hwndDlg, 1504), SW_HIDE); //Domain
225
                SetDlgItemText(hwndDlg, 1502, username);
113 ixe013 226
 
215 ixe013 227
                if(*gEncryptedRandomSelfservePassword)
228
                {
213 ixe013 229
                    //TODO : Decrypt password
215 ixe013 230
                    //CryptUnprotectMemory(gEncryptedRandomSelfservePassword, gEncryptedRandomSelfservePassword_len, CRYPTPROTECTMEMORY_SAME_LOGON);
231
                    TRACE(eINFO, L"Password is %s", gEncryptedRandomSelfservePassword + gEncryptedTag_len - 1);
232
                    SetDlgItemText(hwndDlg, 1503, gEncryptedRandomSelfservePassword + gEncryptedTag_len - 1);
233
                    //TODO : Encrypt memory
234
                    //CryptProtectMemory(gEncryptedRandomSelfservePassword, gEncryptedRandomSelfservePassword_len, CRYPTPROTECTMEMORY_SAME_LOGON);
235
                }
138 ixe013 236
 
215 ixe013 237
                //*/
238
                //No need to post a new message, change this click on the prompt
239
                //to a click on OK
240
                wParam = IDOK;
241
                lParam = (LPARAM)GetDlgItem(hwndDlg, IDOK);
242
            }
243
            else if (wParam == IDOK)
244
            {
245
                if (password_chances > 0)
246
                {
247
                    --password_chances;
248
                }
249
            }
164 ixe013 250
 
215 ixe013 251
            break;
252
        case WM_ENABLE:
164 ixe013 253
 
215 ixe013 254
            if ((wParam == TRUE) && (password_chances == 0) && !hwndPrompt)
255
            {
256
                TRACE(eINFO, L"Clicked OK but credential dialog is shown again.\n");
257
                hwndPrompt = AddStaticPrompt(hwndDlg);
222 ixe013 258
            } else {
259
                ShowWindow(GetDlgItem(hwndDlg, 1502), SW_SHOW); //Username
260
                ShowWindow(GetDlgItem(hwndDlg, 1503), SW_SHOW); //Password
224 ixe013 261
                //Maybe the domain was not there to begin with
223 ixe013 262
                if(domain_was_present)
263
                    ShowWindow(GetDlgItem(hwndDlg, 1504), SW_SHOW); //Domain
215 ixe013 264
            }
122 ixe013 265
 
215 ixe013 266
            break;
267
        case WM_DESTROY:
268
            hwndPrompt = 0;
269
            break;
270
    }
122 ixe013 271
 
215 ixe013 272
    if (!handled)
273
    {
274
        result = gDialogsProc[LOGGED_OUT_SAS_dlg].originalproc(hwndDlg, uMsg, wParam, lParam);
275
    }
122 ixe013 276
 
215 ixe013 277
    return result;
112 ixe013 278
}
137 ixe013 279