1 /* SMB protocol implementation */
4 #define _GNU_SOURCE /* Needed for asprintf() */
12 #ifdef HAVE_LIBSMBCLIENT_H
13 #include <libsmbclient.h>
19 #include <fcntl.h> /* OS/2 needs this after sys/types.h */
27 #include "cache/cache.h"
28 #include "config/options.h"
29 #include "intl/gettext/libintl.h"
30 #include "main/module.h"
31 #include "main/select.h"
32 #include "network/connection.h"
33 #include "network/socket.h"
34 #include "osdep/osdep.h"
35 #include "protocol/auth/auth.h"
36 #include "protocol/common.h"
37 #include "protocol/protocol.h"
38 #include "protocol/smb/smb.h"
39 #include "protocol/uri.h"
40 #include "util/conv.h"
41 #include "util/memory.h"
42 #include "util/snprintf.h"
43 #include "util/string.h"
45 /* These options are not used. */
46 struct option_info smb_options
[] = {
47 INIT_OPT_TREE("protocol", N_("SMB"),
49 N_("SAMBA specific options.")),
51 INIT_OPT_STRING("protocol.smb", N_("Credentials"),
53 N_("Credentials file passed to smbclient via -A option.")),
58 struct module smb_protocol_module
= struct_module(
59 /* name: */ N_("SMB"),
60 /* options: */ smb_options
,
62 /* submodules: */ NULL
,
71 fprintf(stderr
, "text/x-error");
72 printf("%d\n", error
);
77 compare(const void *a
, const void *b
)
79 const struct smbc_dirent
**da
= (const struct smbc_dirent
**)a
;
80 const struct smbc_dirent
**db
= (const struct smbc_dirent
**)b
;
81 int res
= (*da
)->smbc_type
- (*db
)->smbc_type
;
86 return strcmp((*da
)->name
, (*db
)->name
);
90 display_entry(struct smbc_dirent
*entry
, unsigned char dircolor
[])
92 switch (entry
->smbc_type
) {
94 printf("<a href=\"%s\">", entry
->name
);
96 printf("<font color=\"%s\"><b>", dircolor
);
98 printf("%s", entry
->name
);
100 printf("</b></font>");
102 puts("</a> WORKGROUP");
105 printf("<a href=\"%s\">", entry
->name
);
107 printf("<font color=\"%s\"><b>", dircolor
);
109 printf("%s", entry
->name
);
111 printf("</b></font>");
113 printf("</a> SERVER ");
114 puts(entry
->comment
? entry
->comment
: "");
116 case SMBC_FILE_SHARE
:
117 printf("<a href=\"%s\">", entry
->name
);
119 printf("<font color=\"%s\"><b>", dircolor
);
121 printf("%s", entry
->name
);
123 printf("</b></font>");
125 printf("</a> FILE SHARE ");
126 puts(entry
->comment
? entry
->comment
: "");
128 case SMBC_PRINTER_SHARE
:
129 printf("%s PRINTER ", entry
->name
);
130 puts(entry
->comment
? entry
->comment
: "");
132 case SMBC_COMMS_SHARE
:
133 printf("%s COMM\n", entry
->name
);
136 printf("%s IPC\n", entry
->name
);
139 printf("<a href=\"%s\">", entry
->name
);
141 printf("<font color=\"%s\"><b>", dircolor
);
143 printf("%s", entry
->name
);
145 printf("</b></font>");
150 printf("<a href=\"%s\">%s</a> Link\n", entry
->name
, entry
->name
);
153 printf("<a href=\"%s\">%s</a>\n", entry
->name
, entry
->name
);
162 sort_and_display_entries(int dir
, unsigned char dircolor
[])
164 struct smbc_dirent
*fentry
, **table
= NULL
;
168 while ((fentry
= smbc_readdir(dir
))) {
169 struct smbc_dirent
**new_table
, *new_entry
;
170 int length
= fentry
->dirlen
;
172 if (!strcmp(fentry
->name
, "."))
175 new_entry
= mem_alloc(length
);
176 if (fentry
->comment
) {
177 char *comment
= mem_alloc(fentry
->commentlen
+ 1);
179 if (comment
) memcpy(comment
, fentry
->comment
, fentry
->commentlen
+ 1);
180 fentry
->comment
= comment
;
184 new_table
= mem_realloc(table
, (size
+ 1) * sizeof(*table
));
187 memcpy(new_entry
, fentry
, length
);
189 table
[size
] = new_entry
;
192 qsort(table
, size
, sizeof(*table
),
193 (int (*)(const void *, const void *)) compare
);
195 for (i
= 0; i
< size
; i
++) {
196 display_entry(table
[i
], dircolor
);
201 smb_directory(int dir
, struct uri
*uri
)
204 unsigned char dircolor
[8] = "";
206 if (init_directory_listing(&buf
, uri
) != S_OK
) {
207 smb_error(-S_OUT_OF_MEM
);
210 fprintf(stderr
, "text/html");
215 if (get_opt_bool("document.browse.links.color_dirs")) {
216 color_to_string(get_opt_color("document.colors.dirs"),
217 (unsigned char *) &dircolor
);
220 sort_and_display_entries(dir
, dircolor
);
221 puts("</pre><hr/></body></html>");
227 smb_auth(const char *srv
, const char *shr
, char *wg
, int wglen
, char *un
,
228 int unlen
, char *pw
, int pwlen
)
233 #define READ_SIZE 4096
236 do_smb(struct connection
*conn
)
238 unsigned char url_data
[1024];
239 struct uri
*uri
= conn
->uri
;
240 struct auth_entry
*auth
= find_auth(uri
);
244 if ((uri
->userlen
&& uri
->passwordlen
) || !auth
|| !auth
->valid
) {
245 url
= get_uri_string(uri
, URI_BASE
);
247 snprintf(url_data
, 1024, "smb://%s:%s@%s", auth
->user
, auth
->password
,
248 get_uri_string(uri
, URI_HOST
| URI_PORT
| URI_DATA
));
253 smb_error(-S_OUT_OF_MEM
);
255 if (smbc_init(smb_auth
, 0)) {
258 dir
= smbc_opendir(url
);
260 smb_directory(dir
, conn
->uri
);
265 int file
= smbc_open(url
, O_RDONLY
, 0);
271 res
= smbc_fstat(file
, &sb
);
276 fprintf(stderr
, "%" OFF_T_FORMAT
, sb
.st_size
);
279 while ((r
= smbc_read(file
, buf
, READ_SIZE
)) > 0) {
280 if (safe_write(STDOUT_FILENO
, buf
, r
) <= 0)
290 /* Kill the current connection and ask for a username/password for the next
293 prompt_username_pw(struct connection
*conn
)
295 add_auth_entry(conn
->uri
, "Samba", NULL
, NULL
, 0);
296 abort_connection(conn
, S_OK
);
300 smb_got_error(struct socket
*socket
, struct read_buffer
*rb
)
302 int len
= rb
->length
;
303 struct connection
*conn
= socket
->conn
;
307 abort_connection(conn
, -errno
);
311 rb
->data
[len
] = '\0';
312 error
= atoi(rb
->data
);
313 kill_buffer_data(rb
, len
);
316 prompt_username_pw(conn
);
319 abort_connection(conn
, -error
);
325 smb_got_data(struct socket
*socket
, struct read_buffer
*rb
)
327 int len
= rb
->length
;
328 struct connection
*conn
= socket
->conn
;
331 abort_connection(conn
, -errno
);
336 abort_connection(conn
, S_OK
);
340 socket
->state
= SOCKET_END_ONCLOSE
;
341 conn
->received
+= len
;
342 if (add_fragment(conn
->cached
, conn
->from
, rb
->data
, len
) == 1)
345 kill_buffer_data(rb
, len
);
347 read_from_socket(socket
, rb
, S_TRANS
, smb_got_data
);
351 smb_got_header(struct socket
*socket
, struct read_buffer
*rb
)
353 struct connection
*conn
= socket
->conn
;
354 struct read_buffer
*buf
;
357 conn
->cached
= get_cache_entry(conn
->uri
);
360 close(conn
->data_socket
->fd
);
361 abort_connection(conn
, S_OUT_OF_MEM
);
364 socket
->state
= SOCKET_END_ONCLOSE
;
366 if (rb
->length
> 0) {
367 unsigned char *ctype
= memacpy(rb
->data
, rb
->length
);
369 if (ctype
&& *ctype
) {
370 if (!strcmp(ctype
, "text/x-error")) {
374 if (ctype
[0] >= '0' && ctype
[0] <= '9') {
376 conn
->est_length
= (off_t
)atoll(ctype
);
378 conn
->est_length
= (off_t
)atoi(ctype
);
382 else mem_free_set(&conn
->cached
->content_type
, ctype
);
389 buf
= alloc_read_buffer(conn
->data_socket
);
392 close(conn
->data_socket
->fd
);
393 abort_connection(conn
, S_OUT_OF_MEM
);
397 mem_free_set(&conn
->cached
->content_type
, stracpy("text/html"));
398 read_from_socket(conn
->data_socket
, buf
, S_CONN
, smb_got_error
);
400 read_from_socket(conn
->data_socket
, buf
, S_CONN
, smb_got_data
);
405 smb_protocol_handler(struct connection
*conn
)
407 int smb_pipe
[2] = { -1, -1 };
408 int header_pipe
[2] = { -1, -1 };
411 if (c_pipe(smb_pipe
) || c_pipe(header_pipe
)) {
414 if (smb_pipe
[0] >= 0) close(smb_pipe
[0]);
415 if (smb_pipe
[1] >= 0) close(smb_pipe
[1]);
416 if (header_pipe
[0] >= 0) close(header_pipe
[0]);
417 if (header_pipe
[1] >= 0) close(header_pipe
[1]);
418 abort_connection(conn
, -s_errno
);
422 conn
->unrestartable
= 1;
430 close(header_pipe
[0]);
431 close(header_pipe
[1]);
432 retry_connection(conn
, -s_errno
);
437 dup2(smb_pipe
[1], 1);
438 dup2(open("/dev/null", O_RDONLY
), 0);
439 dup2(header_pipe
[1], 2);
441 close(header_pipe
[0]);
443 close_all_non_term_fd();
447 struct read_buffer
*buf2
;
449 conn
->data_socket
->fd
= smb_pipe
[0];
450 conn
->socket
->fd
= header_pipe
[0];
452 close(header_pipe
[1]);
453 buf2
= alloc_read_buffer(conn
->socket
);
456 close(header_pipe
[0]);
457 abort_connection(conn
, S_OUT_OF_MEM
);
460 read_from_socket(conn
->socket
, buf2
, S_CONN
, smb_got_header
);