| 1 |
/*************************************************************************** |
/* SPDX-License-Identifier: GPL-3.0-or-later */ |
| 2 |
net_server.c - description |
/* |
| 3 |
------------------- |
* net_server |
| 4 |
Copyright : (C) 2004-2025 by Leaflet |
* - network server with SSH support |
| 5 |
Email : leaflet@leafok.com |
* |
| 6 |
***************************************************************************/ |
* Copyright (C) 2004-2025 Leaflet <leaflet@leafok.com> |
| 7 |
|
*/ |
|
/*************************************************************************** |
|
|
* * |
|
|
* This program is free software; you can redistribute it and/or modify * |
|
|
* it under the terms of the GNU General Public License as published by * |
|
|
* the Free Software Foundation; either version 3 of the License, or * |
|
|
* (at your option) any later version. * |
|
|
* * |
|
|
***************************************************************************/ |
|
| 8 |
|
|
| 9 |
#include "bbs.h" |
#include "bbs.h" |
| 10 |
#include "bbs_main.h" |
#include "bbs_main.h" |
| 39 |
#include <sys/wait.h> |
#include <sys/wait.h> |
| 40 |
#include <systemd/sd-daemon.h> |
#include <systemd/sd-daemon.h> |
| 41 |
|
|
| 42 |
#define WAIT_CHILD_PROCESS_EXIT_TIMEOUT 5 // second |
enum _net_server_constant_t |
| 43 |
#define WAIT_CHILD_PROCESS_KILL_TIMEOUT 1 // second |
{ |
| 44 |
|
WAIT_CHILD_PROCESS_EXIT_TIMEOUT = 5, // second |
| 45 |
|
WAIT_CHILD_PROCESS_KILL_TIMEOUT = 1, // second |
| 46 |
|
|
| 47 |
|
SSH_AUTH_MAX_DURATION = 60 * 1000, // milliseconds |
| 48 |
|
}; |
| 49 |
|
|
| 50 |
struct process_sockaddr_t |
struct process_sockaddr_t |
| 51 |
{ |
{ |
| 56 |
|
|
| 57 |
static PROCESS_SOCKADDR process_sockaddr_pool[MAX_CLIENT_LIMIT]; |
static PROCESS_SOCKADDR process_sockaddr_pool[MAX_CLIENT_LIMIT]; |
| 58 |
|
|
| 59 |
#define SSH_AUTH_MAX_DURATION (60 * 1000) // milliseconds |
static const char SFTP_SERVER_PATH[] = "/usr/lib/sftp-server"; |
|
|
|
|
#define SFTP_SERVER_PATH "/usr/lib/sftp-server" |
|
| 60 |
|
|
| 61 |
/* A userdata struct for session. */ |
/* A userdata struct for session. */ |
| 62 |
struct session_data_struct |
struct session_data_struct |
| 328 |
|
|
| 329 |
ssh_bind_free(sshbind); |
ssh_bind_free(sshbind); |
| 330 |
|
|
|
ssh_callbacks_init(&channel_cb); |
|
|
ssh_callbacks_init(&server_cb); |
|
|
|
|
|
ssh_set_server_callbacks(SSH_session, &server_cb); |
|
|
|
|
| 331 |
ssh_timeout = 60; // second |
ssh_timeout = 60; // second |
| 332 |
if (ssh_options_set(SSH_session, SSH_OPTIONS_TIMEOUT, &ssh_timeout) < 0) |
if (ssh_options_set(SSH_session, SSH_OPTIONS_TIMEOUT, &ssh_timeout) < 0) |
| 333 |
{ |
{ |
| 335 |
goto cleanup; |
goto cleanup; |
| 336 |
} |
} |
| 337 |
|
|
| 338 |
|
ssh_set_auth_methods(SSH_session, SSH_AUTH_METHOD_PASSWORD); |
| 339 |
|
|
| 340 |
|
ssh_callbacks_init(&server_cb); |
| 341 |
|
ssh_callbacks_init(&channel_cb); |
| 342 |
|
|
| 343 |
|
ssh_set_server_callbacks(SSH_session, &server_cb); |
| 344 |
|
|
| 345 |
if (ssh_handle_key_exchange(SSH_session)) |
if (ssh_handle_key_exchange(SSH_session)) |
| 346 |
{ |
{ |
| 347 |
log_error("ssh_handle_key_exchange() error: %s\n", ssh_get_error(SSH_session)); |
log_error("ssh_handle_key_exchange() error: %s\n", ssh_get_error(SSH_session)); |
| 348 |
goto cleanup; |
goto cleanup; |
| 349 |
} |
} |
|
ssh_set_auth_methods(SSH_session, SSH_AUTH_METHOD_PASSWORD); |
|
| 350 |
|
|
| 351 |
event = ssh_event_new(); |
event = ssh_event_new(); |
| 352 |
ssh_event_add_session(event, SSH_session); |
ssh_event_add_session(event, SSH_session); |
| 371 |
|
|
| 372 |
ssh_set_channel_callbacks(SSH_channel, &channel_cb); |
ssh_set_channel_callbacks(SSH_channel, &channel_cb); |
| 373 |
|
|
| 374 |
|
do |
| 375 |
|
{ |
| 376 |
|
ret = ssh_event_dopoll(event, 100); // 0.1 second |
| 377 |
|
if (ret == SSH_ERROR) |
| 378 |
|
{ |
| 379 |
|
ssh_channel_close(SSH_channel); |
| 380 |
|
} |
| 381 |
|
|
| 382 |
|
if (ret == SSH_AGAIN) // loop until SSH connection is fully established |
| 383 |
|
{ |
| 384 |
|
/* Executed only once, once the child process starts. */ |
| 385 |
|
cdata.event = event; |
| 386 |
|
break; |
| 387 |
|
} |
| 388 |
|
} while (ssh_channel_is_open(SSH_channel)); |
| 389 |
|
|
| 390 |
ssh_timeout = 0; |
ssh_timeout = 0; |
| 391 |
if (ssh_options_set(SSH_session, SSH_OPTIONS_TIMEOUT, &ssh_timeout) < 0) |
if (ssh_options_set(SSH_session, SSH_OPTIONS_TIMEOUT, &ssh_timeout) < 0) |
| 392 |
{ |
{ |
| 682 |
{ |
{ |
| 683 |
if (load_file(data_files_load_startup[i]) < 0) |
if (load_file(data_files_load_startup[i]) < 0) |
| 684 |
{ |
{ |
| 685 |
log_error("load_file_mmap(%s) error\n", data_files_load_startup[i]); |
log_error("load_file(%s) error\n", data_files_load_startup[i]); |
| 686 |
} |
} |
| 687 |
} |
} |
| 688 |
log_common("Reload data files successfully\n"); |
log_common("Reload data files successfully\n"); |