/[LeafOK_CVS]/lbbs/src/test_ssh_server.c
ViewVC logotype

Contents of /lbbs/src/test_ssh_server.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.10 - (show annotations)
Mon Sep 22 05:06:44 2025 UTC (5 months, 3 weeks ago) by sysadm
Branch: MAIN
Changes since 1.9: +20 -1 lines
Content type: text/x-csrc
Add test case for SSH timeout option

1 /***************************************************************************
2 test_ssh_server.c - description
3 -------------------
4 Copyright : (C) 2004-2025 by Leaflet
5 Email : leaflet@leafok.com
6 ***************************************************************************/
7
8 /***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 3 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17 // This test was written based on libssh example/proxy.c
18
19 #include "log.h"
20 #include <stdio.h>
21 #include <libssh/callbacks.h>
22 #include <libssh/libssh.h>
23 #include <libssh/server.h>
24
25 #ifndef BUF_SIZE
26 #define BUF_SIZE 2048
27 #endif
28
29 #define SSH_HOST_RSA_KEYFILE "../conf/ssh_host_rsa_key"
30
31 #define USER "test"
32 #define PASSWORD "123456"
33
34 static ssh_channel SSH_channel;
35 static int authenticated = 0;
36 static int tries = 0;
37 static int error = 0;
38
39 static int auth_password(ssh_session session, const char *user,
40 const char *password, void *userdata)
41 {
42 (void)userdata;
43
44 log_common("Authenticating user %s pwd %s\n", user, password);
45 if (strcmp(user, USER) == 0 && strcmp(password, PASSWORD) == 0)
46 {
47 authenticated = 1;
48 log_common("Authenticated\n");
49 return SSH_AUTH_SUCCESS;
50 }
51 if (tries >= 3)
52 {
53 log_error("Too many authentication tries\n");
54 ssh_disconnect(session);
55 error = 1;
56 return SSH_AUTH_DENIED;
57 }
58 tries++;
59 return SSH_AUTH_DENIED;
60 }
61
62 static int pty_request(ssh_session session, ssh_channel channel, const char *term,
63 int x, int y, int px, int py, void *userdata)
64 {
65 (void)session;
66 (void)channel;
67 (void)term;
68 (void)x;
69 (void)y;
70 (void)px;
71 (void)py;
72 (void)userdata;
73 log_common("Allocated terminal\n");
74 return 0;
75 }
76
77 static int shell_request(ssh_session session, ssh_channel channel, void *userdata)
78 {
79 (void)session;
80 (void)channel;
81 (void)userdata;
82 log_common("Allocated shell\n");
83 return 0;
84 }
85
86 struct ssh_channel_callbacks_struct channel_cb = {
87 .channel_pty_request_function = pty_request,
88 .channel_shell_request_function = shell_request};
89
90 static ssh_channel new_session_channel(ssh_session session, void *userdata)
91 {
92 (void)session;
93 (void)userdata;
94
95 if (SSH_channel != NULL)
96 return NULL;
97
98 log_common("Allocated session channel\n");
99 SSH_channel = ssh_channel_new(session);
100 ssh_callbacks_init(&channel_cb);
101 ssh_set_channel_callbacks(SSH_channel, &channel_cb);
102
103 return SSH_channel;
104 }
105
106 int ssh_server(const char *hostaddr, unsigned int port)
107 {
108 ssh_bind sshbind;
109 ssh_session session;
110 ssh_event event;
111
112 struct ssh_server_callbacks_struct cb = {
113 .userdata = NULL,
114 .auth_password_function = auth_password,
115 .channel_open_request_session_function = new_session_channel};
116
117 long int ssh_timeout = 0;
118
119 char buf[BUF_SIZE];
120 char host[128] = "";
121 int i, r;
122
123 int ssh_log_level = SSH_LOG_PROTOCOL;
124
125 ssh_init();
126
127 sshbind = ssh_bind_new();
128
129 if (ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, hostaddr) < 0 ||
130 ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT, &port) < 0 ||
131 ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, SSH_HOST_RSA_KEYFILE) < 0 ||
132 ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS, "ssh-rsa,rsa-sha2-512,rsa-sha2-256,ecdsa-sha2-nistp256") < 0 ||
133 ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_PUBKEY_ACCEPTED_KEY_TYPES, "ssh-rsa,rsa-sha2-512,rsa-sha2-256,ecdsa-sha2-nistp256") < 0 ||
134 ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_KEY_EXCHANGE, "curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,diffie-hellman-group14-sha1") < 0 ||
135 ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HMAC_C_S, "umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1") < 0 ||
136 ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HMAC_S_C, "umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1") < 0 ||
137 ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_CIPHERS_C_S, "chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com") < 0 ||
138 ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_CIPHERS_S_C, "chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com") < 0 ||
139 ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY, &ssh_log_level) < 0)
140 {
141 log_error("Error setting SSH bind options: %s\n", ssh_get_error(sshbind));
142 ssh_bind_free(sshbind);
143 return -1;
144 }
145
146 if (ssh_bind_listen(sshbind) < 0)
147 {
148 log_error("Error listening at SSH server port: %s\n", ssh_get_error(sshbind));
149 ssh_bind_free(sshbind);
150 return -1;
151 }
152
153 while (1)
154 {
155 session = ssh_new();
156
157 if (ssh_bind_accept(sshbind, session) == SSH_OK)
158 {
159 pid_t pid = fork();
160 switch (pid)
161 {
162 case 0:
163 ssh_bind_free(sshbind);
164
165 ssh_callbacks_init(&cb);
166 ssh_set_server_callbacks(session, &cb);
167
168 ssh_timeout = 60; // second
169 if (ssh_options_set(session, SSH_OPTIONS_TIMEOUT, &ssh_timeout) < 0)
170 {
171 log_error("Error setting SSH options: %s\n", ssh_get_error(session));
172 ssh_disconnect(session);
173 _exit(1);
174 }
175
176 if (ssh_handle_key_exchange(session))
177 {
178 log_error("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
179 ssh_disconnect(session);
180 _exit(1);
181 }
182 ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC);
183
184 event = ssh_event_new();
185 ssh_event_add_session(event, session);
186
187 while (!(authenticated && SSH_channel != NULL))
188 {
189 if (error)
190 break;
191 r = ssh_event_dopoll(event, -1);
192 if (r == SSH_ERROR)
193 {
194 log_error("Error : %s\n", ssh_get_error(session));
195 ssh_disconnect(session);
196 _exit(1);
197 }
198 }
199
200 if (error)
201 {
202 log_error("Error, exiting loop\n");
203 _exit(1);
204 }
205 else
206 {
207 log_common("Authenticated and got a channel\n");
208 }
209
210 ssh_timeout = 0;
211 if (ssh_options_set(session, SSH_OPTIONS_TIMEOUT, &ssh_timeout) < 0)
212 {
213 log_error("Error setting SSH options: %s\n", ssh_get_error(session));
214 ssh_disconnect(session);
215 _exit(1);
216 }
217
218 snprintf(buf, sizeof(buf), "Hello, welcome to the Sample SSH proxy.\r\nPlease select your destination: ");
219 ssh_channel_write(SSH_channel, buf, (uint32_t)strlen(buf));
220 do
221 {
222 i = ssh_channel_read(SSH_channel, buf, sizeof(buf), 0);
223 if (i > 0)
224 {
225 ssh_channel_write(SSH_channel, buf, (uint32_t)i);
226 if (strlen(host) + (size_t)i < sizeof(host))
227 {
228 strncat(host, buf, (size_t)i);
229 }
230 if (strchr(host, '\x0d'))
231 {
232 *strchr(host, '\x0d') = '\0';
233 ssh_channel_write(SSH_channel, "\n", 1);
234 break;
235 }
236 }
237 else
238 {
239 log_error("Error: %s\n", ssh_get_error(session));
240 _exit(1);
241 }
242 } while (i > 0);
243 snprintf(buf, sizeof(buf), "Trying to connect to \"%s\"\r\n", host);
244 ssh_channel_write(SSH_channel, buf, (uint32_t)strlen(buf));
245 log_common("%s", buf);
246
247 ssh_disconnect(session);
248 ssh_free(session);
249
250 _exit(0);
251 case -1:
252 log_error("Failed to fork\n");
253 break;
254 }
255 }
256 else
257 {
258 log_error("%s\n", ssh_get_error(sshbind));
259 }
260
261 /* Since the session has been passed to a child fork, do some cleaning
262 * up at the parent process. */
263 ssh_disconnect(session);
264 ssh_free(session);
265 }
266
267 ssh_bind_free(sshbind);
268 ssh_finalize();
269
270 return 0;
271 }
272
273 int main(int argc, char *argv[])
274 {
275 if (log_begin("../log/bbsd.log", "../log/error.log") < 0)
276 {
277 printf("Open log error\n");
278 return -1;
279 }
280
281 log_common_redir(STDOUT_FILENO);
282 log_error_redir(STDERR_FILENO);
283
284 ssh_server("0.0.0.0", 2322);
285
286 log_end();
287
288 return 0;
289 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1