Coverage Report

Created: 2025-11-11 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libssh/src/callbacks.c
Line
Count
Source
1
/*
2
 * callbacks.c - callback functions
3
 *
4
 * This file is part of the SSH Library
5
 *
6
 * Copyright (c) 2009-2013  by Andreas Schneider <asn@cryptomilk.org>
7
 *
8
 * The SSH Library is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation; either version 2.1 of the License, or (at your
11
 * option) any later version.
12
 *
13
 * The SSH Library is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16
 * License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with the SSH Library; see the file COPYING.  If not, write to
20
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21
 * MA 02111-1307, USA.
22
 */
23
24
#include "config.h"
25
26
#include "libssh/callbacks.h"
27
#include "libssh/misc.h"
28
#include "libssh/session.h"
29
30
#define is_callback_valid(session, cb) \
31
207
    (cb->size > 0 || cb->size <= 1024 * sizeof(void *))
32
33
/* LEGACY */
34
static void ssh_legacy_log_callback(int priority,
35
                                    const char *function,
36
                                    const char *buffer,
37
                                    void *userdata)
38
0
{
39
0
    ssh_session session = (ssh_session)userdata;
40
0
    ssh_log_callback log_fn = session->common.callbacks->log_function;
41
0
    void *log_data = session->common.callbacks->userdata;
42
43
0
    (void)function; /* unused */
44
45
0
    log_fn(session, priority, buffer, log_data);
46
0
}
47
48
void _ssh_remove_legacy_log_cb(void)
49
314
{
50
314
    if (ssh_get_log_callback() == ssh_legacy_log_callback) {
51
0
        _ssh_reset_log_cb();
52
0
        ssh_set_log_userdata(NULL);
53
0
    }
54
314
}
55
56
int ssh_set_callbacks(ssh_session session, ssh_callbacks cb)
57
207
{
58
207
    if (session == NULL || cb == NULL) {
59
0
        return SSH_ERROR;
60
0
    }
61
62
207
    if (!is_callback_valid(session, cb)) {
63
0
        ssh_set_error(session,
64
0
                      SSH_FATAL,
65
0
                      "Invalid callback passed in (badly initialized)");
66
0
        return SSH_ERROR;
67
207
    };
68
207
    session->common.callbacks = cb;
69
70
    /* LEGACY */
71
207
    if (ssh_get_log_callback() == NULL && cb->log_function) {
72
0
        ssh_set_log_callback(ssh_legacy_log_callback);
73
0
        ssh_set_log_userdata(session);
74
0
    }
75
76
207
    return 0;
77
207
}
78
79
static int ssh_add_set_channel_callbacks(ssh_channel channel,
80
                                         ssh_channel_callbacks cb,
81
                                         int prepend)
82
0
{
83
0
    ssh_session session = NULL;
84
0
    int rc;
85
86
0
    if (channel == NULL || cb == NULL) {
87
0
        return SSH_ERROR;
88
0
    }
89
0
    session = channel->session;
90
91
0
    if (!is_callback_valid(session, cb)) {
92
0
        ssh_set_error(session,
93
0
                      SSH_FATAL,
94
0
                      "Invalid callback passed in (badly initialized)");
95
0
        return SSH_ERROR;
96
0
    };
97
0
    if (channel->callbacks == NULL) {
98
0
        channel->callbacks = ssh_list_new();
99
0
        if (channel->callbacks == NULL) {
100
0
            ssh_set_error_oom(session);
101
0
            return SSH_ERROR;
102
0
        }
103
0
    }
104
0
    if (prepend) {
105
0
        rc = ssh_list_prepend(channel->callbacks, cb);
106
0
    } else {
107
0
        rc = ssh_list_append(channel->callbacks, cb);
108
0
    }
109
110
0
    return rc;
111
0
}
112
113
int ssh_set_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb)
114
0
{
115
0
    return ssh_add_set_channel_callbacks(channel, cb, 1);
116
0
}
117
118
int ssh_add_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb)
119
0
{
120
0
    return ssh_add_set_channel_callbacks(channel, cb, 0);
121
0
}
122
123
int ssh_remove_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb)
124
0
{
125
0
    struct ssh_iterator *it = NULL;
126
127
0
    if (channel == NULL || channel->callbacks == NULL) {
128
0
        return SSH_ERROR;
129
0
    }
130
131
0
    it = ssh_list_find(channel->callbacks, cb);
132
0
    if (it == NULL) {
133
0
        return SSH_ERROR;
134
0
    }
135
136
0
    ssh_list_remove(channel->callbacks, it);
137
138
0
    return SSH_OK;
139
0
}
140
141
int ssh_set_server_callbacks(ssh_session session, ssh_server_callbacks cb)
142
0
{
143
0
    if (session == NULL || cb == NULL) {
144
0
        return SSH_ERROR;
145
0
    }
146
147
0
    if (!is_callback_valid(session, cb)) {
148
0
        ssh_set_error(session,
149
0
                      SSH_FATAL,
150
0
                      "Invalid callback passed in (badly initialized)");
151
0
        return SSH_ERROR;
152
0
    };
153
0
    session->server_callbacks = cb;
154
155
0
    return 0;
156
0
}