Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /branches/ssh_chacha20poly1305/ttssh2/ttxssh/auth.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2844 - (hide annotations) (download) (as text)
Mon Sep 5 10:46:22 2005 UTC (18 years, 7 months ago) by yutakakn
Original Path: ttssh2/trunk/ttxssh/auth.c
File MIME type: text/x-csrc
File size: 31626 byte(s)
'/I' 指定があるときのみ認証ダイアログを最小化するようにした。

1 yutakakn 2728 /*
2     Copyright (c) 1998-2001, Robert O'Callahan
3     All rights reserved.
4    
5     Redistribution and use in source and binary forms, with or without modification,
6     are permitted provided that the following conditions are met:
7    
8     Redistributions of source code must retain the above copyright notice, this list of
9     conditions and the following disclaimer.
10    
11     Redistributions in binary form must reproduce the above copyright notice, this list
12     of conditions and the following disclaimer in the documentation and/or other materials
13     provided with the distribution.
14    
15     The name of Robert O'Callahan may not be used to endorse or promote products derived from
16     this software without specific prior written permission.
17    
18     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
19     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21     THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27     */
28    
29     #include "ttxssh.h"
30     #include "util.h"
31 yutakakn 2800 #include "ssh.h"
32 yutakakn 2728
33     #include <io.h>
34     #include <fcntl.h>
35     #include <stdlib.h>
36     #include <errno.h>
37    
38     #include "resource.h"
39     #include "keyfiles.h"
40    
41     #define AUTH_START_USER_AUTH_ON_ERROR_END 1
42    
43     #define MAX_AUTH_CONTROL IDC_SSHUSETIS
44    
45     static void destroy_malloced_string(char FAR * FAR * str)
46     {
47     if (*str != NULL) {
48     memset(*str, 0, strlen(*str));
49     free(*str);
50     *str = NULL;
51     }
52     }
53    
54     static int auth_types_to_control_IDs[] = {
55     -1, IDC_SSHUSERHOSTS, IDC_SSHUSERSA, IDC_SSHUSEPASSWORD,
56     IDC_SSHUSERHOSTS, IDC_SSHUSETIS, -1
57     };
58    
59     static LRESULT CALLBACK password_wnd_proc(HWND control, UINT msg,
60     WPARAM wParam, LPARAM lParam)
61     {
62     switch (msg) {
63     case WM_CHAR:
64     if ((GetKeyState(VK_CONTROL) & 0x8000) != 0) {
65     char chars[] = { (char) wParam, 0 };
66    
67     SendMessage(control, EM_REPLACESEL, (WPARAM) TRUE,
68     (LPARAM) (char FAR *) chars);
69     return 0;
70     }
71     }
72    
73     return CallWindowProc((WNDPROC) GetWindowLong(control, GWL_USERDATA),
74     control, msg, wParam, lParam);
75     }
76    
77     static void init_password_control(HWND dlg)
78     {
79     HWND passwordControl = GetDlgItem(dlg, IDC_SSHPASSWORD);
80    
81     SetWindowLong(passwordControl, GWL_USERDATA,
82     SetWindowLong(passwordControl, GWL_WNDPROC,
83     (LONG) password_wnd_proc));
84    
85     SetFocus(passwordControl);
86     }
87    
88     static void set_auth_options_status(HWND dlg, int controlID)
89     {
90     BOOL RSA_enabled = controlID == IDC_SSHUSERSA;
91     BOOL rhosts_enabled = controlID == IDC_SSHUSERHOSTS;
92     BOOL TIS_enabled = controlID == IDC_SSHUSETIS;
93     int i;
94    
95     CheckRadioButton(dlg, IDC_SSHUSEPASSWORD, MAX_AUTH_CONTROL, controlID);
96    
97     EnableWindow(GetDlgItem(dlg, IDC_SSHPASSWORDCAPTION), !TIS_enabled);
98     EnableWindow(GetDlgItem(dlg, IDC_SSHPASSWORD), !TIS_enabled);
99    
100     for (i = IDC_CHOOSERSAFILE; i <= IDC_RSAFILENAME; i++) {
101     EnableWindow(GetDlgItem(dlg, i), RSA_enabled);
102     }
103    
104     for (i = IDC_LOCALUSERNAMELABEL; i <= IDC_HOSTRSAFILENAME; i++) {
105     EnableWindow(GetDlgItem(dlg, i), rhosts_enabled);
106     }
107     }
108    
109     static void init_auth_machine_banner(PTInstVar pvar, HWND dlg)
110     {
111     char buf[1024] = "Logging in to ";
112    
113     if (strlen(buf) + strlen(SSH_get_host_name(pvar)) < sizeof(buf) - 2) {
114     strcat(buf, SSH_get_host_name(pvar));
115     }
116     SetDlgItemText(dlg, IDC_SSHAUTHBANNER, buf);
117     }
118    
119     static void update_server_supported_types(PTInstVar pvar, HWND dlg)
120     {
121     int supported_methods = pvar->auth_state.supported_types;
122     int cur_control = -1;
123     int control;
124     HWND focus = GetFocus();
125    
126     if (supported_methods == 0) {
127     return;
128     }
129    
130     for (control = IDC_SSHUSEPASSWORD; control <= MAX_AUTH_CONTROL;
131     control++) {
132     BOOL enabled = FALSE;
133     int method;
134     HWND item = GetDlgItem(dlg, control);
135    
136     if (item != NULL) {
137     for (method = 0; method <= SSH_AUTH_MAX; method++) {
138     if (auth_types_to_control_IDs[method] == control
139     && (supported_methods & (1 << method)) != 0) {
140     enabled = TRUE;
141     }
142     }
143    
144     EnableWindow(item, enabled);
145    
146     if (IsDlgButtonChecked(dlg, control)) {
147     cur_control = control;
148     }
149     }
150     }
151    
152     if (cur_control >= 0) {
153     if (!IsWindowEnabled(GetDlgItem(dlg, cur_control))) {
154     do {
155     cur_control++;
156     if (cur_control > MAX_AUTH_CONTROL) {
157     cur_control = IDC_SSHUSEPASSWORD;
158     }
159     } while (!IsWindowEnabled(GetDlgItem(dlg, cur_control)));
160    
161     set_auth_options_status(dlg, cur_control);
162    
163     if (focus != NULL && !IsWindowEnabled(focus)) {
164     SetFocus(GetDlgItem(dlg, cur_control));
165     }
166     }
167     }
168     }
169    
170     static void init_auth_dlg(PTInstVar pvar, HWND dlg)
171     {
172     int default_method = pvar->session_settings.DefaultAuthMethod;
173    
174     init_auth_machine_banner(pvar, dlg);
175     init_password_control(dlg);
176    
177     if (pvar->auth_state.failed_method != SSH_AUTH_NONE) {
178     /* must be retrying a failed attempt */
179     SetDlgItemText(dlg, IDC_SSHAUTHBANNER2,
180     "Authentication failed. Please retry.");
181     SetWindowText(dlg, "Retrying SSH Authentication");
182     default_method = pvar->auth_state.failed_method;
183     }
184    
185     set_auth_options_status(dlg,
186     auth_types_to_control_IDs[default_method]);
187    
188     if (default_method == SSH_AUTH_TIS) {
189     /* we disabled the password control, so fix the focus */
190     SetFocus(GetDlgItem(dlg, IDC_SSHUSETIS));
191     }
192    
193     if (pvar->auth_state.user != NULL) {
194     SetDlgItemText(dlg, IDC_SSHUSERNAME, pvar->auth_state.user);
195     EnableWindow(GetDlgItem(dlg, IDC_SSHUSERNAME), FALSE);
196     EnableWindow(GetDlgItem(dlg, IDC_SSHUSERNAMELABEL), FALSE);
197     } else if (pvar->session_settings.DefaultUserName[0] != 0) {
198     SetDlgItemText(dlg, IDC_SSHUSERNAME,
199     pvar->session_settings.DefaultUserName);
200     } else {
201     SetFocus(GetDlgItem(dlg, IDC_SSHUSERNAME));
202     }
203    
204     SetDlgItemText(dlg, IDC_RSAFILENAME,
205     pvar->session_settings.DefaultRSAPrivateKeyFile);
206     SetDlgItemText(dlg, IDC_HOSTRSAFILENAME,
207     pvar->session_settings.DefaultRhostsHostPrivateKeyFile);
208     SetDlgItemText(dlg, IDC_LOCALUSERNAME,
209     pvar->session_settings.DefaultRhostsLocalUserName);
210    
211     update_server_supported_types(pvar, dlg);
212 yutakakn 2739
213 yutakakn 2784 // SSH2 autologin
214 yutakakn 2739 // ���[�U�A�p�X���[�h�A�F�����\�b�h���������������A������������OK�{�^�������������B
215 yutakakn 2784 //
216     // (2004.12.1 yutaka)
217     // (2005.1.26 yutaka) ���J���F���T�|�[�g
218 yutakakn 2739 if (pvar->ssh2_autologin == 1) {
219     SetDlgItemText(dlg, IDC_SSHUSERNAME, pvar->ssh2_username);
220     EnableWindow(GetDlgItem(dlg, IDC_SSHUSERNAME), FALSE);
221     EnableWindow(GetDlgItem(dlg, IDC_SSHUSERNAMELABEL), FALSE);
222    
223     SetDlgItemText(dlg, IDC_SSHPASSWORD, pvar->ssh2_password);
224     EnableWindow(GetDlgItem(dlg, IDC_SSHPASSWORD), FALSE);
225     EnableWindow(GetDlgItem(dlg, IDC_SSHPASSWORDCAPTION), FALSE);
226    
227 yutakakn 2844 // '/I' �w�������������������������� (2005.9.5 yutaka)
228     if (pvar->ts->Minimize) {
229     //20050822���� start T.Takahashi
230     ShowWindow(dlg,SW_MINIMIZE);
231     //20050822���� end T.Takahashi
232     }
233    
234 yutakakn 2784 if (pvar->ssh2_authmethod == SSH_AUTH_PASSWORD) {
235 yutakakn 2739 CheckRadioButton(dlg, IDC_SSHUSEPASSWORD, MAX_AUTH_CONTROL, IDC_SSHUSEPASSWORD);
236 yutakakn 2784
237     } else if (pvar->ssh2_authmethod == SSH_AUTH_RSA) {
238     CheckRadioButton(dlg, IDC_SSHUSEPASSWORD, MAX_AUTH_CONTROL, IDC_SSHUSERSA);
239    
240     SetDlgItemText(dlg, IDC_RSAFILENAME, pvar->ssh2_keyfile);
241     EnableWindow(GetDlgItem(dlg, IDC_CHOOSERSAFILE), FALSE);
242     EnableWindow(GetDlgItem(dlg, IDC_RSAFILENAME), FALSE);
243    
244 yutakakn 2739 } else {
245     // TODO
246    
247     }
248     }
249    
250 yutakakn 2800 #if 1
251 yutakakn 2799 // �p�X���[�h�F���������O���Akeyboard-interactive���\�b�h�������������A���x������
252     // ���X�����B(2005.3.12 yutaka)
253     if (pvar->settings.ssh2_keyboard_interactive == 1) {
254     SetDlgItemText(dlg, IDC_SSHUSEPASSWORD, "Use p&lain password to log in (with keyboard-interactive)");
255     }
256    
257 yutakakn 2800 if (pvar->settings.ssh_protocol_version == 1) {
258     SetDlgItemText(dlg, IDC_SSHUSETIS, "Use challenge/response to log in(&TIS)");
259     } else {
260 yutakakn 2804 SetDlgItemText(dlg, IDC_SSHUSETIS, "Use challenge/response to log in(&keyboard-interactive)");
261 yutakakn 2800 }
262     #endif
263    
264 yutakakn 2728 }
265    
266     static char FAR *alloc_control_text(HWND ctl)
267     {
268     int len = GetWindowTextLength(ctl);
269     char FAR *result = malloc(len + 1);
270    
271     if (result != NULL) {
272     GetWindowText(ctl, result, len + 1);
273     result[len] = 0;
274     }
275    
276     return result;
277     }
278    
279     static int get_key_file_name(HWND parent, char FAR * buf, int bufsize)
280     {
281     #ifdef TERATERM32
282     OPENFILENAME params;
283     char fullname_buf[2048] = "identity";
284    
285 yutakakn 2762 ZeroMemory(&params, sizeof(params));
286 yutakakn 2728 params.lStructSize = sizeof(OPENFILENAME);
287     params.hwndOwner = parent;
288 yutakakn 2762 // �t�B���^������ (2004.12.19 yutaka)
289 yutakakn 2818 // 3�t�@�C���t�B���^������ (2005.4.26 yutaka)
290     params.lpstrFilter = "identity files\0identity;id_rsa;id_dsa\0identity(RSA1)\0identity\0id_rsa(SSH2)\0id_rsa\0id_dsa(SSH2)\0id_dsa\0all(*.*)\0*.*\0\0";
291 yutakakn 2728 params.lpstrCustomFilter = NULL;
292     params.nFilterIndex = 0;
293     buf[0] = 0;
294     params.lpstrFile = fullname_buf;
295     params.nMaxFile = sizeof(fullname_buf);
296     params.lpstrFileTitle = NULL;
297     params.lpstrInitialDir = NULL;
298 yutakakn 2818 params.lpstrTitle = "Choose a file with the RSA/DSA private key";
299 yutakakn 2728 params.Flags =
300     OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
301     params.lpstrDefExt = NULL;
302    
303     if (GetOpenFileName(&params) != 0) {
304     copy_teraterm_dir_relative_path(buf, bufsize, fullname_buf);
305     return 1;
306     } else {
307     return 0;
308     }
309     #else
310     return 0;
311     #endif
312     }
313    
314     static void choose_RSA_key_file(HWND dlg)
315     {
316     char buf[1024];
317    
318     if (get_key_file_name(dlg, buf, sizeof(buf))) {
319     SetDlgItemText(dlg, IDC_RSAFILENAME, buf);
320     }
321     }
322    
323     static void choose_host_RSA_key_file(HWND dlg)
324     {
325     char buf[1024];
326    
327     if (get_key_file_name(dlg, buf, sizeof(buf))) {
328     SetDlgItemText(dlg, IDC_HOSTRSAFILENAME, buf);
329     }
330     }
331    
332     static BOOL end_auth_dlg(PTInstVar pvar, HWND dlg)
333     {
334     int method = SSH_AUTH_PASSWORD;
335     char FAR *password =
336     alloc_control_text(GetDlgItem(dlg, IDC_SSHPASSWORD));
337     CRYPTKeyPair FAR *key_pair = NULL;
338    
339     if (IsDlgButtonChecked(dlg, IDC_SSHUSERSA)) {
340     method = SSH_AUTH_RSA;
341     } else if (IsDlgButtonChecked(dlg, IDC_SSHUSERHOSTS)) {
342     if (GetWindowTextLength(GetDlgItem(dlg, IDC_HOSTRSAFILENAME)) > 0) {
343     method = SSH_AUTH_RHOSTS_RSA;
344     } else {
345     method = SSH_AUTH_RHOSTS;
346     }
347     } else if (IsDlgButtonChecked(dlg, IDC_SSHUSETIS)) {
348     method = SSH_AUTH_TIS;
349     }
350    
351     if (method == SSH_AUTH_RSA || method == SSH_AUTH_RHOSTS_RSA) {
352     char buf[2048];
353     int file_ctl_ID =
354     method == SSH_AUTH_RSA ? IDC_RSAFILENAME : IDC_HOSTRSAFILENAME;
355    
356     buf[0] = 0;
357     GetDlgItemText(dlg, file_ctl_ID, buf, sizeof(buf));
358     if (buf[0] == 0) {
359     notify_nonfatal_error(pvar,
360 yutakakn 2762 "You must specify a file containing the RSA/DSA private key.");
361 yutakakn 2728 SetFocus(GetDlgItem(dlg, file_ctl_ID));
362     destroy_malloced_string(&password);
363     return FALSE;
364 yutakakn 2762 }
365    
366     if (SSHv1(pvar)) {
367 yutakakn 2728 BOOL invalid_passphrase = FALSE;
368    
369     key_pair = KEYFILES_read_private_key(pvar, buf, password,
370     &invalid_passphrase,
371     FALSE);
372    
373     if (key_pair == NULL) {
374     if (invalid_passphrase) {
375     HWND passwordCtl = GetDlgItem(dlg, IDC_SSHPASSWORD);
376    
377     SetFocus(passwordCtl);
378     SendMessage(passwordCtl, EM_SETSEL, 0, -1);
379     } else {
380     SetFocus(GetDlgItem(dlg, file_ctl_ID));
381     }
382     destroy_malloced_string(&password);
383     return FALSE;
384     }
385 yutakakn 2762
386     } else { // SSH2(yutaka)
387     BOOL invalid_passphrase = FALSE;
388 yutakakn 2769 char errmsg[256];
389 yutakakn 2762
390 yutakakn 2769 memset(errmsg, 0, sizeof(errmsg));
391 yutakakn 2784 //GetCurrentDirectory(sizeof(errmsg), errmsg);
392 yutakakn 2769
393 yutakakn 2762 key_pair = read_SSH2_private_key(pvar, buf, password,
394     &invalid_passphrase,
395 yutakakn 2769 FALSE,
396     errmsg,
397     sizeof(errmsg)
398     );
399 yutakakn 2762
400     if (key_pair == NULL) { // read error
401 yutakakn 2769 char buf[1024];
402     _snprintf(buf, sizeof(buf), "read error SSH2 private key file\r\n%s", errmsg);
403     notify_nonfatal_error(pvar, buf);
404 yutakakn 2762 destroy_malloced_string(&password);
405     return FALSE;
406     }
407    
408 yutakakn 2728 }
409 yutakakn 2762
410 yutakakn 2728 }
411    
412     /* from here on, we cannot fail, so just munge cur_cred in place */
413     pvar->auth_state.cur_cred.method = method;
414     pvar->auth_state.cur_cred.key_pair = key_pair;
415     /* we can't change the user name once it's set. It may already have
416     been sent to the server, and it can only be sent once. */
417     if (pvar->auth_state.user == NULL) {
418     pvar->auth_state.user =
419     alloc_control_text(GetDlgItem(dlg, IDC_SSHUSERNAME));
420     }
421 yutakakn 2811
422     // ���J���F���������A�Z�b�V�������������p�X���[�h���g�����������������������������������B
423     // (2005.4.8 yutaka)
424     if (method == SSH_AUTH_PASSWORD || method == SSH_AUTH_RSA) {
425 yutakakn 2728 pvar->auth_state.cur_cred.password = password;
426     } else {
427     destroy_malloced_string(&password);
428     }
429     if (method == SSH_AUTH_RHOSTS || method == SSH_AUTH_RHOSTS_RSA) {
430     if (pvar->session_settings.DefaultAuthMethod != SSH_AUTH_RHOSTS) {
431     notify_nonfatal_error(pvar,
432     "Rhosts authentication will probably fail because it was not "
433     "the default authentication method.\n"
434     "To use Rhosts authentication "
435     "in TTSSH, you need to set it to be the default by restarting\n"
436     "TTSSH and selecting \"SSH Authentication...\" from the Setup menu"
437     "before connecting.");
438     }
439    
440     pvar->auth_state.cur_cred.rhosts_client_user =
441     alloc_control_text(GetDlgItem(dlg, IDC_LOCALUSERNAME));
442     }
443     pvar->auth_state.auth_dialog = NULL;
444    
445     GetDlgItemText(dlg, IDC_RSAFILENAME,
446     pvar->session_settings.DefaultRSAPrivateKeyFile,
447     sizeof(pvar->session_settings.
448     DefaultRSAPrivateKeyFile));
449     GetDlgItemText(dlg, IDC_HOSTRSAFILENAME,
450     pvar->session_settings.DefaultRhostsHostPrivateKeyFile,
451     sizeof(pvar->session_settings.
452     DefaultRhostsHostPrivateKeyFile));
453     GetDlgItemText(dlg, IDC_LOCALUSERNAME,
454     pvar->session_settings.DefaultRhostsLocalUserName,
455     sizeof(pvar->session_settings.
456     DefaultRhostsLocalUserName));
457    
458     if (SSHv1(pvar)) {
459     SSH_notify_user_name(pvar);
460     SSH_notify_cred(pvar);
461     } else {
462     // for SSH2(yutaka)
463     do_SSH2_userauth(pvar);
464     }
465    
466     EndDialog(dlg, 1);
467     return TRUE;
468     }
469    
470     static BOOL CALLBACK auth_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
471     LPARAM lParam)
472     {
473 yutakakn 2739 const int IDC_TIMER1 = 300;
474 yutakakn 2752 const int autologin_timeout = 10; // �~���b
475 yutakakn 2728 PTInstVar pvar;
476    
477     switch (msg) {
478     case WM_INITDIALOG:
479     pvar = (PTInstVar) lParam;
480     pvar->auth_state.auth_dialog = dlg;
481     SetWindowLong(dlg, DWL_USER, lParam);
482    
483     init_auth_dlg(pvar, dlg);
484 yutakakn 2739
485     // SSH2 autologin���L�����������A�^�C�}���d�|�����B (2004.12.1 yutaka)
486     if (pvar->ssh2_autologin == 1) {
487     SetTimer(dlg, IDC_TIMER1, autologin_timeout, 0);
488     }
489 yutakakn 2728 return FALSE; /* because we set the focus */
490    
491 yutakakn 2739 case WM_TIMER:
492 yutakakn 2752 pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
493     // �F�������������������A�F���f�[�^�����M�����B�����������A�������B(2004.12.16 yutaka)
494     if (!(pvar->ssh_state.status_flags & STATUS_DONT_SEND_USER_NAME)) {
495     KillTimer(dlg, IDC_TIMER1);
496     SendMessage(dlg, WM_COMMAND, IDOK, 0);
497     }
498 yutakakn 2739 return TRUE;
499    
500 yutakakn 2728 case WM_COMMAND:
501     pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
502    
503     switch (LOWORD(wParam)) {
504     case IDOK:
505 yutakakn 2783 // �F�������������������A�F���f�[�^�����M�����B�����������A�������B(2001.1.25 yutaka)
506 yutakakn 2835 if (pvar->userauth_retry_count == 0 && (pvar->ssh_state.status_flags & STATUS_DONT_SEND_USER_NAME)) {
507 yutakakn 2783 return FALSE;
508     }
509 yutakakn 2728 return end_auth_dlg(pvar, dlg);
510    
511     case IDCANCEL: /* kill the connection */
512     pvar->auth_state.auth_dialog = NULL;
513     notify_closed_connection(pvar);
514     EndDialog(dlg, 0);
515     return TRUE;
516    
517     case IDC_SSHUSEPASSWORD:
518     case IDC_SSHUSERSA:
519     case IDC_SSHUSERHOSTS:
520     case IDC_SSHUSETIS:
521     set_auth_options_status(dlg, LOWORD(wParam));
522     return TRUE;
523    
524     case IDC_CHOOSERSAFILE:
525     choose_RSA_key_file(dlg);
526     return TRUE;
527    
528     case IDC_CHOOSEHOSTRSAFILE:
529     choose_host_RSA_key_file(dlg);
530     return TRUE;
531    
532     default:
533     return FALSE;
534     }
535    
536     default:
537     return FALSE;
538     }
539     }
540    
541     char FAR *AUTH_get_user_name(PTInstVar pvar)
542     {
543     return pvar->auth_state.user;
544     }
545    
546     int AUTH_set_supported_auth_types(PTInstVar pvar, int types)
547     {
548     char buf[1024];
549    
550     _snprintf(buf, sizeof(buf),
551     "Server reports supported authentication method mask = %d",
552     types);
553     buf[sizeof(buf) - 1] = 0;
554     notify_verbose_message(pvar, buf, LOG_LEVEL_VERBOSE);
555    
556     if (SSHv1(pvar)) {
557     types &= (1 << SSH_AUTH_PASSWORD) | (1 << SSH_AUTH_RSA)
558     | (1 << SSH_AUTH_RHOSTS_RSA) | (1 << SSH_AUTH_RHOSTS)
559     | (1 << SSH_AUTH_TIS);
560     } else {
561     // for SSH2(yutaka)
562 yutakakn 2762 // types &= (1 << SSH_AUTH_PASSWORD);
563     // ���J���F�����L�������� (2004.12.18 yutaka)
564 yutakakn 2800 // TIS�������BSSH2����keyboard-interactive�����������B(2005.3.12 yutaka)
565 yutakakn 2762 types &= (1 << SSH_AUTH_PASSWORD) | (1 << SSH_AUTH_RSA)
566 yutakakn 2800 | (1 << SSH_AUTH_DSA)
567     | (1 << SSH_AUTH_TIS);
568 yutakakn 2728 }
569     pvar->auth_state.supported_types = types;
570    
571     if (types == 0) {
572     notify_fatal_error(pvar,
573     "Server does not support any of the authentication options\n"
574     "provided by TTSSH. This connection will now close.");
575     return 0;
576     } else {
577     if (pvar->auth_state.auth_dialog != NULL) {
578     update_server_supported_types(pvar,
579     pvar->auth_state.auth_dialog);
580     }
581    
582     return 1;
583     }
584     }
585    
586     static void start_user_auth(PTInstVar pvar)
587     {
588 yutakakn 2739 // �F���_�C�A���O���\�������� (2004.12.1 yutaka)
589 yutakakn 2728 PostMessage(pvar->NotificationWindow, WM_COMMAND, (WPARAM) ID_SSHAUTH,
590     (LPARAM) NULL);
591     pvar->auth_state.cur_cred.method = SSH_AUTH_NONE;
592     }
593    
594     static void try_default_auth(PTInstVar pvar)
595     {
596     if (pvar->session_settings.TryDefaultAuth) {
597     switch (pvar->session_settings.DefaultAuthMethod) {
598     case SSH_AUTH_RSA:{
599     BOOL invalid_passphrase;
600     char password[] = "";
601    
602     pvar->auth_state.cur_cred.key_pair
603     =
604     KEYFILES_read_private_key(pvar,
605     pvar->session_settings.
606     DefaultRSAPrivateKeyFile,
607     password,
608     &invalid_passphrase, TRUE);
609     if (pvar->auth_state.cur_cred.key_pair == NULL) {
610     return;
611     } else {
612     pvar->auth_state.cur_cred.method = SSH_AUTH_RSA;
613     }
614     break;
615     }
616    
617     case SSH_AUTH_RHOSTS:
618     if (pvar->session_settings.
619     DefaultRhostsHostPrivateKeyFile[0] != 0) {
620     BOOL invalid_passphrase;
621     char password[] = "";
622    
623     pvar->auth_state.cur_cred.key_pair
624     =
625     KEYFILES_read_private_key(pvar,
626     pvar->session_settings.
627     DefaultRhostsHostPrivateKeyFile,
628     password,
629     &invalid_passphrase, TRUE);
630     if (pvar->auth_state.cur_cred.key_pair == NULL) {
631     return;
632     } else {
633     pvar->auth_state.cur_cred.method = SSH_AUTH_RHOSTS_RSA;
634     }
635     } else {
636     pvar->auth_state.cur_cred.method = SSH_AUTH_RHOSTS;
637     }
638    
639     pvar->auth_state.cur_cred.rhosts_client_user =
640     _strdup(pvar->session_settings.DefaultRhostsLocalUserName);
641     break;
642    
643     case SSH_AUTH_PASSWORD:
644     pvar->auth_state.cur_cred.password = _strdup("");
645     pvar->auth_state.cur_cred.method = SSH_AUTH_PASSWORD;
646     break;
647    
648     case SSH_AUTH_TIS:
649     default:
650     return;
651     }
652    
653     pvar->auth_state.user =
654     _strdup(pvar->session_settings.DefaultUserName);
655     }
656     }
657    
658     void AUTH_notify_end_error(PTInstVar pvar)
659     {
660     if ((pvar->auth_state.flags & AUTH_START_USER_AUTH_ON_ERROR_END) != 0) {
661     start_user_auth(pvar);
662     pvar->auth_state.flags &= ~AUTH_START_USER_AUTH_ON_ERROR_END;
663     }
664     }
665    
666     void AUTH_advance_to_next_cred(PTInstVar pvar)
667     {
668     pvar->auth_state.failed_method = pvar->auth_state.cur_cred.method;
669    
670     if (pvar->auth_state.cur_cred.method == SSH_AUTH_NONE) {
671     try_default_auth(pvar);
672    
673     if (pvar->auth_state.cur_cred.method == SSH_AUTH_NONE) {
674     if (pvar->err_msg != NULL) {
675     pvar->auth_state.flags |=
676     AUTH_START_USER_AUTH_ON_ERROR_END;
677     } else {
678 yutakakn 2739 // �������F���_�C�A���O���o�������� (2004.12.1 yutaka)
679     // �R�}���h���C���w������������
680 yutakakn 2728 start_user_auth(pvar);
681     }
682     }
683     } else {
684 yutakakn 2739 // �������F���_�C�A���O���o�������� (2004.12.1 yutaka)
685     // �R�}���h���C���w������(/auth=xxxx)������
686 yutakakn 2728 start_user_auth(pvar);
687     }
688     }
689    
690     static void init_TIS_dlg(PTInstVar pvar, HWND dlg)
691     {
692     init_auth_machine_banner(pvar, dlg);
693     init_password_control(dlg);
694    
695     if (pvar->auth_state.TIS_prompt != NULL) {
696     if (strlen(pvar->auth_state.TIS_prompt) > 10000) {
697     pvar->auth_state.TIS_prompt[10000] = 0;
698     }
699     SetDlgItemText(dlg, IDC_SSHAUTHBANNER2,
700     pvar->auth_state.TIS_prompt);
701     destroy_malloced_string(&pvar->auth_state.TIS_prompt);
702     }
703     }
704    
705     static BOOL end_TIS_dlg(PTInstVar pvar, HWND dlg)
706     {
707     char FAR *password =
708     alloc_control_text(GetDlgItem(dlg, IDC_SSHPASSWORD));
709    
710     pvar->auth_state.cur_cred.method = SSH_AUTH_TIS;
711     pvar->auth_state.cur_cred.password = password;
712     pvar->auth_state.auth_dialog = NULL;
713    
714 yutakakn 2800 // add
715     if (SSHv2(pvar)) {
716     pvar->keyboard_interactive_password_input = 1;
717     handle_SSH2_userauth_inforeq(pvar);
718     }
719    
720 yutakakn 2728 SSH_notify_cred(pvar);
721    
722     EndDialog(dlg, 1);
723     return TRUE;
724     }
725    
726     static BOOL CALLBACK TIS_dlg_proc(HWND dlg, UINT msg, WPARAM wParam,
727     LPARAM lParam)
728     {
729     PTInstVar pvar;
730    
731     switch (msg) {
732     case WM_INITDIALOG:
733     pvar = (PTInstVar) lParam;
734     pvar->auth_state.auth_dialog = dlg;
735     SetWindowLong(dlg, DWL_USER, lParam);
736    
737     init_TIS_dlg(pvar, dlg);
738     return FALSE; /* because we set the focus */
739    
740     case WM_COMMAND:
741     pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
742    
743     switch (LOWORD(wParam)) {
744     case IDOK:
745     return end_TIS_dlg(pvar, dlg);
746    
747     case IDCANCEL: /* kill the connection */
748     pvar->auth_state.auth_dialog = NULL;
749     notify_closed_connection(pvar);
750     EndDialog(dlg, 0);
751     return TRUE;
752    
753     default:
754     return FALSE;
755     }
756    
757     default:
758     return FALSE;
759     }
760     }
761    
762     void AUTH_do_cred_dialog(PTInstVar pvar)
763     {
764     if (pvar->auth_state.auth_dialog == NULL) {
765     HWND cur_active = GetActiveWindow();
766     DLGPROC dlg_proc;
767     LPCTSTR dialog_template;
768    
769     switch (pvar->auth_state.mode) {
770     case TIS_AUTH_MODE:
771     dialog_template = MAKEINTRESOURCE(IDD_SSHTISAUTH);
772     dlg_proc = TIS_dlg_proc;
773     break;
774     case GENERIC_AUTH_MODE:
775     default:
776     dialog_template = MAKEINTRESOURCE(IDD_SSHAUTH);
777     dlg_proc = auth_dlg_proc;
778     }
779    
780     if (!DialogBoxParam(hInst, dialog_template,
781     cur_active !=
782     NULL ? cur_active : pvar->NotificationWindow,
783     dlg_proc, (LPARAM) pvar) == -1) {
784     notify_fatal_error(pvar,
785     "Unable to display authentication dialog box.\n"
786     "Connection terminated.");
787     }
788     }
789     }
790    
791     static void init_default_auth_dlg(PTInstVar pvar, HWND dlg)
792     {
793     switch (pvar->settings.DefaultAuthMethod) {
794     case SSH_AUTH_RSA:
795     CheckRadioButton(dlg, IDC_SSHUSEPASSWORD, MAX_AUTH_CONTROL,
796     IDC_SSHUSERSA);
797     break;
798     case SSH_AUTH_RHOSTS:
799     case SSH_AUTH_RHOSTS_RSA:
800     CheckRadioButton(dlg, IDC_SSHUSEPASSWORD, MAX_AUTH_CONTROL,
801     IDC_SSHUSERHOSTS);
802     break;
803     case SSH_AUTH_TIS:
804     CheckRadioButton(dlg, IDC_SSHUSEPASSWORD, MAX_AUTH_CONTROL,
805     IDC_SSHUSETIS);
806     break;
807     case SSH_AUTH_PASSWORD:
808     default:
809     CheckRadioButton(dlg, IDC_SSHUSEPASSWORD, MAX_AUTH_CONTROL,
810     IDC_SSHUSEPASSWORD);
811     }
812    
813     SetDlgItemText(dlg, IDC_SSHUSERNAME, pvar->settings.DefaultUserName);
814     SetDlgItemText(dlg, IDC_RSAFILENAME,
815     pvar->settings.DefaultRSAPrivateKeyFile);
816     SetDlgItemText(dlg, IDC_HOSTRSAFILENAME,
817     pvar->settings.DefaultRhostsHostPrivateKeyFile);
818     SetDlgItemText(dlg, IDC_LOCALUSERNAME,
819     pvar->settings.DefaultRhostsLocalUserName);
820 yutakakn 2789
821     // SSH2 keyboard-interactive method (2005.2.22 yutaka)
822     if (pvar->settings.ssh2_keyboard_interactive) {
823     SendMessage(GetDlgItem(dlg, IDC_KEYBOARD_INTERACTIVE_CHECK), BM_SETCHECK, BST_CHECKED, 0);
824     }
825    
826 yutakakn 2728 }
827    
828     static BOOL end_default_auth_dlg(PTInstVar pvar, HWND dlg)
829     {
830     if (IsDlgButtonChecked(dlg, IDC_SSHUSERSA)) {
831     pvar->settings.DefaultAuthMethod = SSH_AUTH_RSA;
832     } else if (IsDlgButtonChecked(dlg, IDC_SSHUSERHOSTS)) {
833     if (GetWindowTextLength(GetDlgItem(dlg, IDC_HOSTRSAFILENAME)) > 0) {
834     pvar->settings.DefaultAuthMethod = SSH_AUTH_RHOSTS_RSA;
835     } else {
836     pvar->settings.DefaultAuthMethod = SSH_AUTH_RHOSTS;
837     }
838     } else if (IsDlgButtonChecked(dlg, IDC_SSHUSETIS)) {
839     pvar->settings.DefaultAuthMethod = SSH_AUTH_TIS;
840     } else {
841     pvar->settings.DefaultAuthMethod = SSH_AUTH_PASSWORD;
842     }
843    
844     GetDlgItemText(dlg, IDC_SSHUSERNAME, pvar->settings.DefaultUserName,
845     sizeof(pvar->settings.DefaultUserName));
846     GetDlgItemText(dlg, IDC_RSAFILENAME,
847     pvar->settings.DefaultRSAPrivateKeyFile,
848     sizeof(pvar->settings.DefaultRSAPrivateKeyFile));
849     GetDlgItemText(dlg, IDC_HOSTRSAFILENAME,
850     pvar->settings.DefaultRhostsHostPrivateKeyFile,
851     sizeof(pvar->settings.DefaultRhostsHostPrivateKeyFile));
852     GetDlgItemText(dlg, IDC_LOCALUSERNAME,
853     pvar->settings.DefaultRhostsLocalUserName,
854     sizeof(pvar->settings.DefaultRhostsLocalUserName));
855    
856 yutakakn 2789 // SSH2 keyboard-interactive method (2005.2.22 yutaka)
857     {
858     LRESULT ret;
859     ret = SendMessage(GetDlgItem(dlg, IDC_KEYBOARD_INTERACTIVE_CHECK), BM_GETCHECK, 0, 0);
860     if (ret & BST_CHECKED) {
861     pvar->settings.ssh2_keyboard_interactive = 1;
862     } else {
863     pvar->settings.ssh2_keyboard_interactive = 0;
864     }
865     }
866    
867 yutakakn 2728 EndDialog(dlg, 1);
868     return TRUE;
869     }
870    
871     static BOOL CALLBACK default_auth_dlg_proc(HWND dlg, UINT msg,
872     WPARAM wParam, LPARAM lParam)
873     {
874     PTInstVar pvar;
875    
876     switch (msg) {
877     case WM_INITDIALOG:
878     pvar = (PTInstVar) lParam;
879     SetWindowLong(dlg, DWL_USER, lParam);
880    
881     init_default_auth_dlg(pvar, dlg);
882     return TRUE; /* because we do not set the focus */
883    
884     case WM_COMMAND:
885     pvar = (PTInstVar) GetWindowLong(dlg, DWL_USER);
886    
887     switch (LOWORD(wParam)) {
888     case IDOK:
889     return end_default_auth_dlg(pvar, dlg);
890    
891     case IDCANCEL:
892     EndDialog(dlg, 0);
893     return TRUE;
894    
895     case IDC_CHOOSERSAFILE:
896     choose_RSA_key_file(dlg);
897     return TRUE;
898    
899     case IDC_CHOOSEHOSTRSAFILE:
900     choose_host_RSA_key_file(dlg);
901     return TRUE;
902    
903     default:
904     return FALSE;
905     }
906    
907     default:
908     return FALSE;
909     }
910     }
911    
912     void AUTH_init(PTInstVar pvar)
913     {
914     pvar->auth_state.failed_method = SSH_AUTH_NONE;
915     pvar->auth_state.auth_dialog = NULL;
916     pvar->auth_state.user = NULL;
917     pvar->auth_state.flags = 0;
918     pvar->auth_state.TIS_prompt = NULL;
919     pvar->auth_state.supported_types = 0;
920     pvar->auth_state.cur_cred.method = SSH_AUTH_NONE;
921     pvar->auth_state.cur_cred.password = NULL;
922     pvar->auth_state.cur_cred.rhosts_client_user = NULL;
923     pvar->auth_state.cur_cred.key_pair = NULL;
924     AUTH_set_generic_mode(pvar);
925     }
926    
927     void AUTH_set_generic_mode(PTInstVar pvar)
928     {
929     pvar->auth_state.mode = GENERIC_AUTH_MODE;
930     destroy_malloced_string(&pvar->auth_state.TIS_prompt);
931     }
932    
933     void AUTH_set_TIS_mode(PTInstVar pvar, char FAR * prompt, int len)
934     {
935     if (pvar->auth_state.cur_cred.method == SSH_AUTH_TIS) {
936     pvar->auth_state.mode = TIS_AUTH_MODE;
937    
938     destroy_malloced_string(&pvar->auth_state.TIS_prompt);
939     pvar->auth_state.TIS_prompt = malloc(len + 1);
940     memcpy(pvar->auth_state.TIS_prompt, prompt, len);
941     pvar->auth_state.TIS_prompt[len] = 0;
942     } else {
943     AUTH_set_generic_mode(pvar);
944     }
945     }
946    
947     void AUTH_do_default_cred_dialog(PTInstVar pvar)
948     {
949     HWND cur_active = GetActiveWindow();
950    
951     if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SSHAUTHSETUP),
952     cur_active !=
953     NULL ? cur_active : pvar->NotificationWindow,
954     default_auth_dlg_proc, (LPARAM) pvar) == -1) {
955     notify_nonfatal_error(pvar,
956     "Unable to display authentication setup dialog box.");
957     }
958     }
959    
960     void AUTH_destroy_cur_cred(PTInstVar pvar)
961     {
962     destroy_malloced_string(&pvar->auth_state.cur_cred.password);
963     destroy_malloced_string(&pvar->auth_state.cur_cred.rhosts_client_user);
964     if (pvar->auth_state.cur_cred.key_pair != NULL) {
965     CRYPT_free_key_pair(pvar->auth_state.cur_cred.key_pair);
966     pvar->auth_state.cur_cred.key_pair = NULL;
967     }
968     }
969    
970     static char FAR *get_auth_method_name(SSHAuthMethod auth)
971     {
972     switch (auth) {
973     case SSH_AUTH_PASSWORD:
974     return "password";
975     case SSH_AUTH_RSA:
976     return "RSA";
977     case SSH_AUTH_RHOSTS:
978     return "rhosts";
979     case SSH_AUTH_RHOSTS_RSA:
980     return "rhosts with RSA";
981     case SSH_AUTH_TIS:
982     return "challenge/response (TIS)";
983     default:
984     return "unknown method";
985     }
986     }
987    
988     void AUTH_get_auth_info(PTInstVar pvar, char FAR * dest, int len)
989     {
990 yutakakn 2782 char *method = "unknown";
991    
992 yutakakn 2728 if (pvar->auth_state.user == NULL) {
993     strncpy(dest, "None", len);
994     } else if (pvar->auth_state.cur_cred.method != SSH_AUTH_NONE) {
995 yutakakn 2762 if (SSHv1(pvar)) {
996     _snprintf(dest, len, "User '%s', using %s", pvar->auth_state.user,
997     get_auth_method_name(pvar->auth_state.cur_cred.method));
998    
999 yutakakn 2800 } else {
1000     // SSH2:�F�����\�b�h������ (2004.12.23 yutaka)
1001     // keyboard-interactive���\�b�h������ (2005.3.12 yutaka)
1002     if (pvar->auth_state.cur_cred.method == SSH_AUTH_PASSWORD ||
1003     pvar->auth_state.cur_cred.method == SSH_AUTH_TIS) {
1004 yutakakn 2782 // keyboard-interactive���\�b�h������ (2005.1.24 yutaka)
1005 yutakakn 2800 if (pvar->keyboard_interactive_done == 1 ||
1006     pvar->auth_state.cur_cred.method == SSH_AUTH_TIS) {
1007 yutakakn 2782 method = "keyboard-interactive";
1008     } else {
1009     method = get_auth_method_name(pvar->auth_state.cur_cred.method);
1010     }
1011     _snprintf(dest, len, "User '%s', using %s", pvar->auth_state.user, method);
1012    
1013 yutakakn 2762 } else {
1014     if (pvar->auth_state.cur_cred.key_pair->RSA_key != NULL) {
1015     method = "RSA";
1016     } else if (pvar->auth_state.cur_cred.key_pair->DSA_key != NULL) {
1017     method = "DSA";
1018     }
1019     _snprintf(dest, len, "User '%s', using %s", pvar->auth_state.user, method);
1020     }
1021    
1022     }
1023    
1024 yutakakn 2728 } else {
1025     _snprintf(dest, len, "User '%s', using %s", pvar->auth_state.user,
1026     get_auth_method_name(pvar->auth_state.failed_method));
1027     }
1028    
1029     dest[len - 1] = 0;
1030     }
1031    
1032     void AUTH_notify_disconnecting(PTInstVar pvar)
1033     {
1034     if (pvar->auth_state.auth_dialog != NULL) {
1035     PostMessage(pvar->auth_state.auth_dialog, WM_COMMAND, IDCANCEL, 0);
1036     /* the main window might not go away if it's not enabled. (see vtwin.cpp) */
1037     EnableWindow(pvar->NotificationWindow, TRUE);
1038     }
1039     }
1040    
1041     void AUTH_end(PTInstVar pvar)
1042     {
1043     destroy_malloced_string(&pvar->auth_state.user);
1044     destroy_malloced_string(&pvar->auth_state.TIS_prompt);
1045    
1046     AUTH_destroy_cur_cred(pvar);
1047     }
1048 yutakakn 2739
1049     /*
1050     * $Log: not supported by cvs2svn $
1051 yutakakn 2844 * Revision 1.16 2005/08/26 16:26:02 yutakakn
1052     * �������O�C������SSH�F���_�C�A���O�����������������������B
1053     *
1054 yutakakn 2841 * Revision 1.15 2005/07/15 14:58:04 yutakakn
1055     * SSH1���������x���[�U�F�������s�������A�������F�����������������o�O���C���B
1056     *
1057 yutakakn 2835 * Revision 1.14 2005/04/26 13:57:57 yutakakn
1058     * private key�t�@�C���_�C�A���O��3�t�@�C���t�B���^�����������B
1059     *
1060 yutakakn 2818 * Revision 1.13 2005/04/08 14:55:03 yutakakn
1061     * "Duplicate session"��������SSH�������O�C�����s�������������B
1062     *
1063 yutakakn 2811 * Revision 1.12 2005/03/23 12:39:35 yutakakn
1064     * SSH2�F���_�C�A���O�� Use challenge/response to log in ���A�N�Z�����[�^�L�[�������������B
1065     *
1066 yutakakn 2804 * Revision 1.11 2005/03/12 15:07:33 yutakakn
1067     * SSH2 keyboard-interactive�F����TIS�_�C�A���O�����������B
1068     *
1069 yutakakn 2800 * Revision 1.10 2005/03/12 12:08:05 yutakakn
1070     * �p�X���[�h�F�����O���s��keyboard-interactive���\�b�h���A�f�t�H���g�����l������(0)�������B
1071     * �����A�F���_�C�A���O�����x�������������L�����������X���������������B
1072     *
1073 yutakakn 2799 * Revision 1.9 2005/02/22 08:48:11 yutakakn
1074     * TTSSH setup�_�C�A���O�� HeartBeat �����������B
1075     * TTSSH authentication setup�_�C�A���O�� keyboard-interactive �����������B
1076     *
1077 yutakakn 2789 * Revision 1.8 2005/01/27 13:30:33 yutakakn
1078     * ���J���F���������O�C�����T�|�[�g�B
1079     * /auth=publickey, /keyfile �I�v�V�������V�K���������B
1080     * �����A�����������������T�|�[�g�B
1081     *
1082 yutakakn 2784 * Revision 1.7 2005/01/25 13:38:22 yutakakn
1083     * SSH�F���_�C�A���O���ARhosts/TIS���O���[�������O���AEnter�L�[�������������A
1084     * �A�v���P�[�V�����G���[���������������������B
1085     *
1086 yutakakn 2783 * Revision 1.6 2005/01/24 14:07:07 yutakakn
1087     * �Ekeyboard-interactive�F�����T�|�[�g�����B
1088     * �@�����������Ateraterm.ini�� "KeyboardInteractive" �G���g�������������B
1089     * �E�o�[�W�����_�C�A���O�� OpenSSL�o�[�W���� ������
1090     *
1091 yutakakn 2782 * Revision 1.5 2004/12/27 14:35:41 yutakakn
1092     * SSH2�����������������s�����G���[���b�Z�[�W�����������B
1093     *
1094 yutakakn 2769 * Revision 1.4 2004/12/22 17:28:14 yutakakn
1095     * SSH2���J���F��(RSA/DSA)���T�|�[�g�����B
1096     *
1097 yutakakn 2762 * Revision 1.3 2004/12/16 13:01:09 yutakakn
1098     * SSH�������O�C�����A�v���P�[�V�����G���[�������������C�������B
1099     *
1100 yutakakn 2752 * Revision 1.2 2004/12/01 15:37:49 yutakakn
1101     * SSH2�������O�C���@�\�������B
1102     * �����A�p�X���[�h�F�������������B
1103     * �E�R�}���h���C��
1104     * /ssh /auth=�F�����\�b�h /user=���[�U�� /passwd=�p�X���[�h
1105     *
1106 yutakakn 2739 */

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26