1 /*
2 * Copyright (c) 2013 Lukasz Marek <lukasz.m.luki@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <fcntl.h>
23 #include <libssh/sftp.h>
30
41
43 {
44 static const int verbosity = SSH_LOG_NOLOG;
45
46 if (!(libssh->
session = ssh_new())) {
49 }
50 ssh_options_set(libssh->
session, SSH_OPTIONS_HOST, hostname);
51 ssh_options_set(libssh->
session, SSH_OPTIONS_PORT, &port);
52 ssh_options_set(libssh->
session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
55 ssh_options_set(libssh->
session, SSH_OPTIONS_TIMEOUT_USEC, &timeout);
56 }
57
58 if (ssh_options_parse_config(libssh->
session,
NULL) < 0) {
60 }
61
62 if (ssh_connect(libssh->
session) != SSH_OK) {
65 }
66
67 return 0;
68 }
69
71 {
72 int authorized = 0;
73 int auth_methods;
74
75 if (user)
76 ssh_options_set(libssh->
session, SSH_OPTIONS_USER, user);
77
78 if (ssh_userauth_none(libssh->
session,
NULL) == SSH_AUTH_SUCCESS)
79 return 0;
80
81 auth_methods = ssh_userauth_list(libssh->
session,
NULL);
82
83 if (auth_methods & SSH_AUTH_METHOD_PUBLICKEY) {
85 ssh_string pub_key;
86 ssh_private_key priv_key;
88 if (!ssh_try_publickey_from_file(libssh->
session, libssh->
priv_key, &pub_key, &type)) {
89 priv_key = privatekey_from_file(libssh->
session, libssh->
priv_key, type, password);
90 if (ssh_userauth_pubkey(libssh->
session,
NULL, pub_key, priv_key) == SSH_AUTH_SUCCESS) {
91 av_log(libssh,
AV_LOG_DEBUG,
"Authentication successful with selected private key.\n");
92 authorized = 1;
93 }
94 } else {
97 }
98 }
else if (ssh_userauth_autopubkey(libssh->
session, password) == SSH_AUTH_SUCCESS) {
100 authorized = 1;
101 }
102 }
103
104 if (!authorized && (auth_methods & SSH_AUTH_METHOD_PASSWORD)) {
105 if (ssh_userauth_password(libssh->
session,
NULL, password) == SSH_AUTH_SUCCESS) {
107 authorized = 1;
108 }
109 }
110
111 if (!authorized) {
114 }
115
116 return 0;
117 }
118
120 {
124 }
125
126 if (sftp_init(libssh->
sftp) != SSH_OK) {
129 }
130
131 return 0;
132 }
133
135 {
136 int access;
137
139 access = O_CREAT | O_RDWR;
141 access |= O_TRUNC;
142 } else if (flags & AVIO_FLAG_WRITE) {
143 access = O_CREAT | O_WRONLY;
145 access |= O_TRUNC;
146 } else
147 access = O_RDONLY;
148
149 /* 0666 = -rw-rw-rw- = read+write for everyone, minus umask */
150 if (!(libssh->
file = sftp_open(libssh->
sftp, file, access, 0666))) {
153 }
154
155 return 0;
156 }
157
159 {
160 sftp_attributes stat;
161
162 if (!(stat = sftp_fstat(libssh->
file))) {
165 } else {
167 sftp_attributes_free(stat);
168 }
169 }
170
172 {
175 sftp_close(libssh->
file);
177 }
179 sftp_free(libssh->
sftp);
181 }
183 ssh_disconnect(libssh->
session);
186 }
187 return 0;
188 }
189
191 {
193 char proto[10], path[
MAX_URL_SIZE], hostname[1024], credencials[1024];
197
199 credencials, sizeof(credencials),
200 hostname, sizeof(hostname),
201 &port,
202 path, sizeof(path),
203 url);
204
205 // a port of 0 will use a port from ~/.ssh/config or the default value 22
206 if (port < 0 || port > 65535)
207 port = 0;
208
210 goto fail;
211
212 user =
av_strtok(credencials,
":", &end);
214
216 goto fail;
217
219 goto fail;
220
222 goto fail;
223
225
226 return 0;
227
228 fail:
231 }
232
234 {
236 int64_t newpos;
237
241 }
242
243 switch(whence) {
246 case SEEK_SET:
247 newpos = pos;
248 break;
249 case SEEK_CUR:
250 newpos = sftp_tell64(libssh->
file) + pos;
251 break;
252 case SEEK_END:
254 break;
255 default:
257 }
258
259 if (newpos < 0) {
262 }
263
264 if (sftp_seek64(libssh->
file, newpos)) {
267 }
268
269 return newpos;
270 }
271
273 {
275 int bytes_read;
276
277 if ((bytes_read = sftp_read(libssh->
file, buf, size)) < 0) {
280 }
281 return bytes_read;
282 }
283
285 {
287 int bytes_written;
288
289 if ((bytes_written = sftp_write(libssh->
file, buf, size)) < 0) {
292 }
293 return bytes_written;
294 }
295
296 #define OFFSET(x) offsetof(LIBSSHContext, x)
297 #define D AV_OPT_FLAG_DECODING_PARAM
298 #define E AV_OPT_FLAG_ENCODING_PARAM
300 {
"timeout",
"set timeout of socket I/O operations",
OFFSET(rw_timeout),
AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX,
D|
E },
304 };
305
311 };
312
321 .priv_data_class = &libssh_context_class,
323 };
void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, const char *url)
Split a URL string into components.
static av_cold int libssh_open(URLContext *h, const char *url, int flags)
#define URL_PROTOCOL_FLAG_NETWORK
static int libssh_write(URLContext *h, const unsigned char *buf, int size)
#define AV_LOG_WARNING
Something somehow does not look correct.
#define LIBAVUTIL_VERSION_INT
#define AVIO_FLAG_READ
read-only
#define AVIO_FLAG_WRITE
write-only
Macro definitions for various function/variable attributes.
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
static av_cold int end(AVCodecContext *avctx)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
static av_cold int libssh_create_ssh_session(LIBSSHContext *libssh, const char *hostname, unsigned int port)
static av_cold int libssh_create_sftp_session(LIBSSHContext *libssh)
static av_cold int libssh_authentication(LIBSSHContext *libssh, const char *user, const char *password)
static av_always_inline av_const double trunc(double x)
static av_cold int libssh_open_file(LIBSSHContext *libssh, int flags, const char *file)
static av_cold int libssh_close(URLContext *h)
static const AVClass libssh_context_class
static int64_t libssh_seek(URLContext *h, int64_t pos, int whence)
Describe the class of an AVClass context structure.
static const AVOption options[]
static int libssh_read(URLContext *h, unsigned char *buf, int size)
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok()...
#define AVSEEK_SIZE
Passing this as the "whence" parameter to a seek function causes it to return the filesize without se...
URLProtocol ff_libssh_protocol
static av_cold void libssh_stat_file(LIBSSHContext *libssh)
unbuffered private I/O API