source: branches/client-3.0/src/smbwrp.c@ 936

Last change on this file since 936 was 936, checked in by Paul Smedley, 9 years ago

Log the negotiated SMB protocol

  • Property svn:eol-style set to native
File size: 32.4 KB
Line 
1/*
2 Netdrive Samba client plugin
3 samba library wrappers
4 Copyright (C) netlabs.org 2003-2008
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program 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
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include "includes.h"
22#include "rpc_client/cli_pipe.h"
23#include "librpc/gen_ndr/ndr_srvsvc_c.h"
24#include "libsmb/libsmb.h"
25#include "libsmb/clirap.h"
26#include "param.h"
27#include "smb/smbXcli_base.h"
28#include "trans2.h"
29#include "smbwrp.h"
30#include "util.h"
31
32/*
33 * Wrapper for cli_errno to return not connected error on negative fd
34 * Now returns an OS/2 return code instead of lerrno.
35 */
36int os2cli_errno(cli_state * cli)
37{
38#if 0 // cli->fd not available in Samba 4.x
39 if (cli->fd == -1)
40 {
41 return maperror( ENOTCONN);
42 }
43#endif
44 return maperror(cli_errno(cli));
45}
46
47void smbwrp_Logging()
48{
49 char slogfile[_MAX_PATH +1] = {0};
50 char slogfilename[] = "log.smbc";
51 char *env = getenv("LOGFILES");
52 if (env != NULL)
53 {
54 strncpy(slogfile, env, sizeof(slogfile) -1);
55 strncat(slogfile, "\\", sizeof(slogfile) - strlen(slogfile) -1);
56 strncat(slogfile, slogfilename, sizeof(slogfile) - strlen(slogfile) -1);
57 }
58 else
59 {
60 strncpy(slogfile, slogfilename, sizeof(slogfile) -1);
61 }
62
63 // init samba for debug messages
64 setup_logging(slogfile, DEBUG_FILE);
65 lp_set_logfile(slogfile);
66 reopen_logs();
67}
68
69const char * smbwrp_getVersion()
70{
71 return samba_version_string();
72}
73
74int _System smbwrp_getclisize(void)
75{
76 return sizeof(struct cli_state);
77}
78
79/*****************************************************
80initialise structures
81*******************************************************/
82int _System smbwrp_init(void)
83{
84 static int initialised = 0;
85 char *p;
86
87 struct loadparm_context *lp_ctx;
88 TALLOC_CTX *frame = talloc_stackframe();
89
90 if (initialised)
91 {
92 return 0;
93 }
94 initialised = 1;
95
96 smb_init_locale();
97
98 if (!lp_load_client(get_dyn_CONFIGFILE())) {
99 debuglocal(0,("Can't load %s, defaults are used!\n",get_dyn_CONFIGFILE()));
100 }
101 load_interfaces();
102
103 if (!init_names())
104 {
105 return 1;
106 }
107
108 if (writeLog())
109 {
110 smbwrp_Logging();
111 }
112
113/*
114 if ((p=smbw_getshared("RESOLVE_ORDER"))) {
115 lp_set_name_resolve_order(p);
116 }
117*/
118 return 0;
119
120}
121
122void smbwrp_initthread(void)
123{
124 /*
125 Block SIGPIPE (from lib/util_sock.c: write())
126 It is not needed and should not stop execution
127 */
128 BlockSignals(True, SIGPIPE);
129}
130
131#if 0
132/*****************************************************
133remove redundent stuff from a filename
134*******************************************************/
135void clean_fname(char *name)
136{
137 char *p, *p2;
138 int l;
139 int modified = 1;
140
141 if (!name) return;
142
143 while (modified) {
144 modified = 0;
145
146 if ((p=strstr(name,"/./"))) {
147 modified = 1;
148 while (*p) {
149 p[0] = p[2];
150 p++;
151 }
152 }
153
154 if ((p=strstr(name,"//"))) {
155 modified = 1;
156 while (*p) {
157 p[0] = p[1];
158 p++;
159 }
160 }
161
162 if (strcmp(name,"/../")==0) {
163 modified = 1;
164 name[1] = 0;
165 }
166
167 if ((p=strstr(name,"/../"))) {
168 modified = 1;
169 for (p2=(p>name?p-1:p);p2>name;p2--) {
170 if (p2[0] == '/') break;
171 }
172 while (*p2) {
173 p2[0] = p2[3];
174 p2++;
175 }
176 }
177
178 if (strcmp(name,"/..")==0) {
179 modified = 1;
180 name[1] = 0;
181 }
182
183 l = strlen(name);
184 p = l>=3?(name+l-3):name;
185 if (strcmp(p,"/..")==0) {
186 modified = 1;
187 for (p2=p-1;p2>name;p2--) {
188 if (p2[0] == '/') break;
189 }
190 if (p2==name) {
191 p[0] = '/';
192 p[1] = 0;
193 } else {
194 p2[0] = 0;
195 }
196 }
197
198 l = strlen(name);
199 p = l>=2?(name+l-2):name;
200 if (strcmp(p,"/.")==0) {
201 if (p == name) {
202 p[1] = 0;
203 } else {
204 p[0] = 0;
205 }
206 }
207
208 if (strncmp(p=name,"./",2) == 0) {
209 modified = 1;
210 do {
211 p[0] = p[2];
212 } while (*p++);
213 }
214
215 l = strlen(p=name);
216 if (l > 1 && p[l-1] == '/') {
217 modified = 1;
218 p[l-1] = 0;
219 }
220 }
221}
222#endif
223
224/*****************************************************
225return a connection to a server
226loosely based on do_connect() from libsmb/clidfs.c
227*******************************************************/
228int _System smbwrp_connect( Resource* pRes, cli_state ** cli)
229{
230 smbwrp_server * srv = &pRes->srv;
231 char * server = srv->server_name;
232 char * share = *(srv->share_name) ? srv->share_name : "IPC$";
233 char * workgroup = srv->workgroup;
234 struct nmb_name called, calling;
235 char *p, *server_n = server;
236 struct cli_state * c;
237 char* dev_type;
238 int loginerror = 0;
239 NTSTATUS status;
240 int max_protocol = lp__client_max_protocol();
241 int port = 0; //NBT_SMB_PORT;
242 int name_type= 0x20;
243 int flags = 0;
244 enum protocol_types protocol;
245 const char *name = NULL;
246
247 if (!pRes->krb5support)
248 debuglocal(1,"Connecting to \\\\%s:*********@%s:%s\\%s. Master %s:%d\n", srv->username, workgroup, server, share, srv->master, srv->ifmastergroup);
249 else
250 debuglocal(1,"Connecting to \\\\%s:%s\\%s using kerberos authentication. Master %s:%d\n", workgroup, server, share, srv->master, srv->ifmastergroup);
251
252 if (pRes->krb5support) {
253 flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
254 }
255
256 if (pRes->ntlmv1support) {
257 lp_set_cmdline("client ntlmv2 auth","no");
258 }
259
260 status = cli_connect_nb(
261 server, NULL, port, name_type, NULL,
262 SMB_SIGNING_DEFAULT, flags, &c);
263
264 if (!NT_STATUS_IS_OK(status)) {
265 debuglocal(4,"Connection to %s failed (Error %s)\n",
266 server,
267 nt_errstr(status));
268 return 3;
269 }
270
271 if (max_protocol == PROTOCOL_DEFAULT) {
272 max_protocol = PROTOCOL_LATEST;
273 }
274 DEBUG(4,(" session request ok, c->timeout = %d\n",c->timeout));
275
276 status = smbXcli_negprot(c->conn, c->timeout,
277 lp_client_min_protocol(),
278 max_protocol);
279
280 if (!NT_STATUS_IS_OK(status)) {
281 debuglocal(4,"protocol negotiation failed: %s\n",
282 nt_errstr(status));
283 cli_shutdown(c);
284 return status;
285 }
286
287 protocol = smbXcli_conn_protocol(c->conn);
288
289 switch (protocol) {
290 case PROTOCOL_CORE:
291 name = "CORE";
292 break;
293 case PROTOCOL_COREPLUS:
294 name = "COREPLUS";
295 break;
296 case PROTOCOL_LANMAN1:
297 name = "LANMAN1";
298 break;
299 case PROTOCOL_LANMAN2:
300 name = "LANMAN2";
301 break;
302 case PROTOCOL_NT1:
303 name = "NT1";
304 break;
305 case PROTOCOL_SMB2_02:
306 name = "SMB2_02";
307 break;
308 case PROTOCOL_SMB2_10:
309 name = "SMB2_10";
310 break;
311 case PROTOCOL_SMB2_22:
312 name = "SMB2_22";
313 break;
314 case PROTOCOL_SMB2_24:
315 name = "SMB2_24";
316 break;
317 case PROTOCOL_SMB3_00:
318 name = "SMB3_00";
319 break;
320 case PROTOCOL_SMB3_02:
321 name = "SMB3_02";
322 break;
323 case PROTOCOL_SMB3_10:
324 name = "SMB3_10";
325 break;
326 case PROTOCOL_SMB3_11:
327 name = "SMB3_11";
328 break;
329 default:
330 name = "Unknown";
331 break;
332 }
333
334 debuglocal(4,"Server supports %s protocol\n", name);
335
336 if (smbXcli_conn_protocol(c->conn) >= PROTOCOL_SMB2_02) {
337 /* Ensure we ask for some initial credits. */
338 smb2cli_conn_set_max_credits(c->conn, DEFAULT_SMB2_MAX_CREDITS);
339 }
340
341 if (!NT_STATUS_IS_OK(cli_session_setup(c, srv->username,
342 srv->password, strlen(srv->password),
343 srv->password, strlen(srv->password),
344 workgroup))) {
345 debuglocal(4,"%s/******** login failed\n", srv->username);
346 loginerror = 1; // save the login error
347
348 /* try an anonymous login if it failed */
349
350 /* If a password was not supplied then
351 * try again with a null username. */
352 if (srv->password[0] || !srv->username[0] ||
353 pRes->krb5support ||
354 !NT_STATUS_IS_OK(status = cli_session_setup(c, "",
355 "", 0,
356 "", 0,
357 workgroup))) {
358 debuglocal(1,"session setup failed: %s\n",
359 nt_errstr(status));
360
361 if ((NT_STATUS_EQUAL(status,
362 NT_STATUS_MORE_PROCESSING_REQUIRED)) ||
363 NT_STATUS_EQUAL(status,
364 NT_STATUS_INTERNAL_ERROR)){
365 debuglocal(4,"did you forget to run kinit?\n");
366 } else
367 debuglocal(4,"Anonymous login failed\n");
368
369 cli_shutdown(c);
370 return 6;
371 }
372 debuglocal(4,"Anonymous login successful\n");
373 }
374
375 if (!NT_STATUS_IS_OK(status)) {
376 debuglocal(4,"cli_init_creds() failed\n");
377 cli_shutdown(c);
378 // if loginerror is != 0 means normal login failed, but anonymous login worked
379 if (loginerror !=0)
380 return 6;
381 else
382 return 7;
383 }
384
385 debuglocal(4," session setup ok. Sending tconx <%s> <********>\n", share);
386
387 // YD ticket:58 we need to check resource type to avoid connecting to printers.
388 // dev type is set to IPC for IPC$, A: for everything else (printers use LPT1:)
389 if (!strcmp( share, "IPC$"))
390 dev_type = "IPC";
391 else
392 dev_type = "A:";
393
394 if (!NT_STATUS_IS_OK(cli_tcon_andx(c, share, dev_type,
395 srv->password, strlen(srv->password)+1))) {
396 cli_shutdown(c);
397 // if loginerror is != 0 means normal login failed, but anonymous login worked
398 if (loginerror !=0)
399 return 6;
400 else
401 return 7;
402 }
403
404 debuglocal(4," tconx ok.\n");
405
406 // save cli_state pointer
407 *cli = c;
408
409 return 0;
410}
411
412/*****************************************************
413close a connection to a server
414*******************************************************/
415void _System smbwrp_disconnect( Resource* pRes, cli_state * cli)
416{
417 if (pRes && cli)
418 {
419 // this call will free all buffers, close handles and free cli mem
420 cli_shutdown( cli);
421 }
422}
423
424
425
426/*****************************************************
427a wrapper for open()
428*******************************************************/
429int _System smbwrp_open(cli_state * cli, smbwrp_file * file)
430{
431 uint16_t fd = 0;
432
433 if (!cli || !file || !*file->fname)
434 {
435 return maperror(EINVAL);
436 }
437 if (file->denymode < DENY_ALL || file->denymode > DENY_NONE)
438 {
439 file->denymode = DENY_NONE;
440 }
441
442 debuglocal(4,"cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode);
443 if (!NT_STATUS_IS_OK(cli_open(cli, file->fname, file->openmode, file->denymode, &fd)))
444 {
445 return os2cli_errno(cli);
446 }
447 file->fd = fd;
448 file->updatetime = 0;
449 file->offset = 0;
450 return 0;
451}
452
453/*****************************************************
454a wrapper for read()
455*******************************************************/
456int _System smbwrp_read(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
457{
458 int ret;
459
460 if (!cli || !file || !buf || !result)
461 {
462 return maperror(EINVAL);
463 }
464 size_t nread;
465 *result = 0;
466 ret = cli_read(cli, file->fd, buf, file->offset, count, &nread);
467 if (ret == -1)
468 {
469 debuglocal(4," smbwrp_read - cli_read ret = %d\n",ret);
470 return os2cli_errno(cli);
471 }
472
473 file->offset += nread;
474 *result = nread;
475 debuglocal(4," smbwrp_read successful, nread = %d, ret = %d\n",nread,ret);
476 return 0;
477}
478
479
480
481/*****************************************************
482a wrapper for write()
483*******************************************************/
484int _System smbwrp_write(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
485{
486 NTSTATUS status;
487 size_t ret;
488
489 if (!cli || !file || !buf || !result)
490 {
491 return maperror(EINVAL);
492 }
493
494 *result = 0;
495//debuglocal(1,("Write %x %d %lld %d", cli, file->fd, file->offset, count));
496 status = cli_writeall(cli, file->fd, 0, buf, file->offset, count, &ret);
497 if (!NT_STATUS_IS_OK(status)) {
498 return os2cli_errno(cli);
499 }
500
501 file->updatetime = 1;
502 file->offset += ret;
503 *result = ret;
504 return 0;
505}
506
507/*****************************************************
508a wrapper for close()
509*******************************************************/
510int _System smbwrp_close(cli_state * cli, smbwrp_file * file)
511{
512 int rc = 0;
513 if (!cli || !file)
514 {
515 return maperror(EINVAL);
516 }
517
518 debuglocal(4,"smpwrp_close updatetime: %d\n", file->updatetime);
519
520 if (file->updatetime == 1)
521 {
522 file->mtime = time(NULL);
523 debuglocal(4,"cli_close new mtime %lu\n", file->mtime);
524 }
525
526 if (!NT_STATUS_IS_OK(cli_close(cli, file->fd)))
527 {
528 rc = os2cli_errno(cli);
529 }
530
531 if (!rc && (file->openattr || file->mtime || file->ctime))
532 {
533 debuglocal(4,"Set pathinfo on close %s %08x %d %d\n", file->fname, file->openattr, file->mtime, file->ctime);
534 if (!NT_STATUS_IS_OK(cli_setpathinfo_basic(cli, file->fname, file->ctime, 0, file->mtime, 0, file->openattr)))
535 {
536 debuglocal(4,"Set pathinfo on close failed %d\n", os2cli_errno(cli));
537 //rc = os2cli_errno(cli);
538 }
539 }
540
541 file->openattr = 0;
542 file->mtime = 0;
543 file->ctime = 0;
544 file->updatetime = 0;
545 file->fd = -1;
546 file->offset = 0;
547 *file->fname = 0;
548 return rc;
549}
550
551int _System smbwrp_setfilesize(cli_state * cli, smbwrp_file * file, long long newsize)
552{
553 int rc = 0;
554 if (!cli || !file)
555 {
556 return maperror(EINVAL);
557 }
558
559 debuglocal(4,"cli_setnewfilesize(%s) %lld\n", file->fname, newsize);
560 if (!NT_STATUS_IS_OK(cli_ftruncate(cli, file->fd, newsize)))
561 {
562 if (newsize)
563 {
564 rc = os2cli_errno(cli);
565 }
566
567 if (!NT_STATUS_IS_OK(cli_close(cli, file->fd)))
568 {
569 return os2cli_errno(cli);
570 }
571 uint16_t fd = 0;
572 file->fd = -1;
573 file->offset = 0;
574 file->openmode &= ~(O_CREAT | O_EXCL);
575 file->openmode |= O_TRUNC;
576 debuglocal(4,"cli_setnewfileszie : cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode);
577 if (!NT_STATUS_IS_OK(cli_open(cli, file->fname, file->openmode, file->denymode, &fd)))
578 {
579 return os2cli_errno(cli);
580 }
581 file->fd = fd;
582 }
583 return 0;
584}
585
586/*****************************************************
587a wrapper for rename()
588*******************************************************/
589int _System smbwrp_rename(cli_state * cli, char *oldname, char *newname)
590{
591 if (!cli || !oldname || !newname)
592 {
593 return maperror(EINVAL);
594 }
595
596 debuglocal(1,"Rename <%s> -> <%s>\n", oldname, newname);
597 if (!NT_STATUS_IS_OK(cli_rename(cli, oldname, newname)))
598 {
599 return os2cli_errno(cli);
600 }
601 return 0;
602}
603
604
605/*****************************************************
606a wrapper for chmod()
607*******************************************************/
608int _System smbwrp_setattr(cli_state * cli, smbwrp_fileinfo *finfo)
609{
610 if (!cli || !finfo || !*finfo->fname)
611 {
612 return maperror(EINVAL);
613 }
614
615debuglocal(4,"Setting on <%s> attr %04x, time %lu (timezone /%lu\n", finfo->fname, finfo->attr, finfo->mtime, finfo->mtime + get_time_zone(finfo->mtime));
616 // we already have gmt time, so no need to add timezone
617 // if (!cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime + (finfo->mtime == 0 ? 0 : get_time_zone(finfo->mtime)))
618 if (!NT_STATUS_IS_OK(cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime))
619 && !NT_STATUS_IS_OK(cli_setatr(cli, finfo->fname, finfo->attr, 0)))
620 {
621 return os2cli_errno(cli);
622 }
623 return 0;
624}
625
626/*****************************************************
627a wrapper for unlink()
628*******************************************************/
629int _System smbwrp_unlink(cli_state * cli, const char *fname)
630{
631 if (!cli || !fname)
632 {
633 return maperror(EINVAL);
634 }
635#if 0
636 if (strncmp(cli->dev, "LPT", 3) == 0)
637 {
638 int job = smbw_stat_printjob(cli, fname, NULL, NULL);
639 if (job == -1)
640 {
641 goto failed;
642 }
643 if (cli_printjob_del(cli, job) != 0)
644 {
645 goto failed;
646 }
647 } else
648#endif
649 if (!NT_STATUS_IS_OK(cli_unlink(cli, fname, aSYSTEM | aHIDDEN)))
650 {
651 return os2cli_errno(cli);
652 }
653 return 0;
654}
655
656/*****************************************************
657a wrapper for lseek()
658*******************************************************/
659int _System smbwrp_lseek(cli_state * cli, smbwrp_file * file, int whence, long long offset)
660{
661 off_t size;
662 if (!cli || !file)
663 {
664 return maperror(EINVAL);
665 }
666
667 debuglocal(4,"lseek %d %lld %lld\n", whence, offset, file->offset);
668
669 switch (whence) {
670 case SEEK_SET:
671 if (offset < 0)
672 {
673 return maperror(EINVAL);
674 }
675 file->offset = offset;
676 break;
677 case SEEK_CUR:
678 file->offset += offset;
679 break;
680 case SEEK_END:
681 if (offset > 0)
682 {
683 return maperror(EINVAL);
684 }
685 if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(cli, file->fd,
686 NULL, &size, NULL, NULL, NULL,
687 NULL, NULL)) &&
688 !NT_STATUS_IS_OK(cli_getattrE(cli, file->fd,
689 NULL, &size, NULL, NULL, NULL)))
690 {
691 return os2cli_errno(cli);
692 }
693 file->offset = size + offset;
694 break;
695 default: return maperror(EINVAL);
696 }
697
698 return 0;
699}
700
701/*****************************************************
702try to do a QPATHINFO and if that fails then do a getatr
703this is needed because win95 sometimes refuses the qpathinfo
704*******************************************************/
705int _System smbwrp_getattr(smbwrp_server *srv, cli_state * cli, smbwrp_fileinfo *finfo)
706{
707 SMB_INO_T ino = 0;
708 struct timespec ctime;
709 struct timespec mtime;
710 struct timespec atime;
711
712 if (!cli || !finfo || !*finfo->fname)
713 {
714 return maperror(EINVAL);
715 }
716 debuglocal(4,"getattr %d %d <%s>\n", smb1cli_conn_capabilities(cli->conn) & CAP_NOPATHINFO2, smb1cli_conn_capabilities(cli->conn) & CAP_NT_SMBS, finfo->fname);
717
718 if (NT_STATUS_IS_OK(cli_qpathinfo2(cli, finfo->fname, &ctime, &atime, &mtime, NULL,
719 (off_t *)&finfo->size, (unsigned short *)&finfo->attr, &ino)))
720 {
721 finfo->attr &= 0x7F;
722 finfo->ctime = convert_timespec_to_time_t(ctime);
723 finfo->atime = convert_timespec_to_time_t(atime);
724 finfo->mtime = convert_timespec_to_time_t(mtime);
725 return 0;
726 }
727
728#if 0 // cli->fd not available in Samba 4.x
729 if (cli->fd == -1)
730 {
731 /* fd == -1 means the connection is broken */
732 return maperror(ENOTCONN);
733 }
734#endif
735
736 debuglocal(4, "smbwrp_getattr, calling cli_qpathinfo3\n");
737 if (NT_STATUS_IS_OK(cli_qpathinfo3(cli, finfo->fname, &ctime, &atime, &mtime, NULL,
738 (off_t *)&finfo->size, (unsigned short *)&finfo->attr, &ino)))
739 {
740 finfo->attr &= 0x7F;
741 finfo->ctime = convert_timespec_to_time_t(ctime);
742 finfo->atime = convert_timespec_to_time_t(atime);
743 finfo->mtime = convert_timespec_to_time_t(mtime);
744 return 0;
745 }
746
747 /* If the path is not on a share (it is a workgroup or a server),
748 * then cli_qpathinfo2 obviously fails. Return some fake information
749 * about the directory.
750 */
751 if ( *srv->server_name == 0
752 || (strcmp(cli->dev,"IPC") == 0)
753 || *srv->share_name == 0
754 || (stricmp(srv->share_name,"IPC$") == 0)
755 || (strncmp(cli->dev,"LPT",3) == 0)
756 )
757 {
758 debuglocal(4,"getattr not a share.\n");
759 *(time_t *)&finfo->ctime = time (NULL);
760 *(time_t *)&finfo->atime = time (NULL);
761 *(time_t *)&finfo->mtime = time (NULL);
762 finfo->size = 0;
763 finfo->easize = 0;
764 finfo->attr = aDIR;
765 return 0;
766 }
767
768 /* if this is NT then don't bother with the getatr */
769 if (smb1cli_conn_capabilities(cli->conn) & CAP_NT_SMBS/* && !(smb1cli_conn_capabilities(cli->conn) & CAP_NOPATHINFO2)*/)
770 {
771 int ret = cli_errno(cli);
772 // cli_qpathinfo* reports EINVAL when path of given file not exists
773 // thus there is no real situation when EINVAL should be returned to
774 // client at this point, we just replace it to ENOTDIR
775 if (ret == EINVAL)
776 {
777 ret = ENOTDIR;
778 }
779 return maperror(ret);
780 }
781
782 if (NT_STATUS_IS_OK(cli_getatr(cli, finfo->fname, (unsigned short *)&finfo->attr, &finfo->size, (time_t *)&finfo->mtime)))
783 {
784//debuglocal(2,("gotattr1 %08x <%s>\n", finfo->attr, finfo->fname));
785 finfo->mtime -= get_time_zone(finfo->mtime);
786 finfo->atime = finfo->atime; //was mtime
787 finfo->ctime = finfo->ctime; //was mtime
788 return 0;
789 }
790 return os2cli_errno(cli);
791}
792
793/*****************************************************
794try to do a QPATHINFO and if that fails then do a getatr
795this is needed because win95 sometimes refuses the qpathinfo
796*******************************************************/
797int _System smbwrp_fgetattr(cli_state * cli, smbwrp_file *file, smbwrp_fileinfo *finfo)
798{
799 struct timespec ctime;
800 struct timespec mtime;
801 struct timespec atime;
802 SMB_INO_T ino = 0;
803
804 if (!cli || !file || !finfo)
805 {
806 return maperror(EINVAL);
807 }
808
809 strncpy(finfo->fname, file->fname, sizeof(finfo->fname) - 1);
810 if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(cli, file->fd,
811 (unsigned short *)&finfo->attr, (off_t *)&finfo->size, &ctime, &atime, &mtime, NULL,
812 &ino)))
813 {
814 if (!NT_STATUS_IS_OK(cli_getattrE(cli, file->fd,
815 (unsigned short *)&finfo->attr, (&finfo->size), (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime)))
816 {
817 return os2cli_errno(cli);
818 }
819 else
820 {
821 finfo->ctime -= get_time_zone(finfo->ctime);
822 finfo->atime -= get_time_zone(finfo->atime);
823 finfo->mtime -= get_time_zone(finfo->mtime);
824 }
825 }
826 else
827 {
828 finfo->ctime = convert_timespec_to_time_t(ctime);
829 finfo->atime = convert_timespec_to_time_t(atime);
830 finfo->mtime = convert_timespec_to_time_t(mtime);
831 }
832
833 return 0;
834}
835
836// =============================DIRECTORY ROUTINES============================
837
838/*****************************************************
839add a entry to a directory listing
840*******************************************************/
841static NTSTATUS smbwrp_dir_add(const char* mnt, smbwrp_fileinfo *finfo, const char *mask, void *state)
842{
843 if (state && finfo)
844 {
845 filelist_state * st = (filelist_state *)state;
846 char fullname[ _MAX_PATH] = {0};
847 debuglocal(8,"adding <%s> %d %d %d\n", finfo->fname, sizeof(st->finfo), st->datalen, sizeof(st->finfo.fname));
848 memcpy(&st->finfo, finfo, sizeof(st->finfo));
849 strncpy(fullname, st->dir, strlen(st->dir));
850 strncat(fullname, finfo->fname, sizeof(fullname) - strlen(fullname) -1);
851 strncpy(st->finfo.fname, fullname, sizeof(st->finfo.fname));
852 getfindinfoL( st->pConn, st->plist, &st->finfo, st->ulAttribute, st->dir_mask);
853 }
854}
855
856static void smbwrp_special_add(const char * name, void * state)
857{
858 smbwrp_fileinfo finfo = {0};
859
860 if (!name)
861 {
862 return;
863 }
864
865 ZERO_STRUCT(finfo);
866
867 strncpy(finfo.fname, name, sizeof(finfo.fname) - 1);
868 finfo.attr = aRONLY | aDIR;
869
870 smbwrp_dir_add("", &finfo, NULL, state);
871}
872
873static NTSTATUS smbwrp_printjob_add(struct print_job_info *job, void * state)
874{
875 smbwrp_fileinfo finfo = {0};
876
877 ZERO_STRUCT(finfo);
878
879//printf("Printjob <%s>\n", job->name);
880
881 strncpy(finfo.fname, job->name, sizeof(finfo.fname) - 1);
882 finfo.mtime = job->t - get_time_zone(job->t);
883 finfo.atime = finfo.atime; //was mtime
884 finfo.ctime = finfo.ctime; //was mtime
885 finfo.attr = aRONLY;
886 finfo.size = job->size;
887
888 smbwrp_dir_add("", &finfo, NULL, state);
889}
890
891static void smbwrp_share_add(const char *share, uint32_t type,
892 const char *comment, void *state)
893{
894 smbwrp_fileinfo finfo = {0};
895
896 // strip administrative names and printers from list
897 if (type == STYPE_PRINTQ || strcmp(share,"IPC$") == 0) return;
898
899 ZERO_STRUCT(finfo);
900
901 strncpy(finfo.fname, share, sizeof(finfo.fname) - 1);
902 finfo.attr = aRONLY | aDIR;
903
904 smbwrp_dir_add("", &finfo, NULL, state);
905}
906
907/****************************************************************************
908 Do a directory listing, calling fn on each file found.
909 Modified from cli_list
910****************************************************************************/
911static int list_files(struct cli_state *cli, const char *mask, uint16_t attribute,
912 void (*fn)(const char *, smbwrp_fileinfo *, const char *,
913 void *), void *state)
914{
915 TALLOC_CTX *frame = talloc_stackframe();
916 struct event_context *ev;
917 struct tevent_req *req;
918 NTSTATUS status = NT_STATUS_NO_MEMORY;
919 struct file_info *finfo;
920 size_t i, num_finfo;
921 uint16_t info_level;
922 void *dircachectx = NULL;
923 smbwrp_fileinfo wrpfinfo;
924
925 /* Try to get the listing from cache. */
926 if (dircache_list_files(fn, state, &num_finfo))
927 {
928 /* Got from cache. */
929 return(num_finfo);
930 }
931
932 if (smbXcli_conn_has_async_calls(cli->conn)) {
933 /*
934 * Can't use sync call while an async call is in flight
935 */
936 status = NT_STATUS_INVALID_PARAMETER;
937 goto fail;
938 }
939 ev = samba_tevent_context_init(frame);
940 if (ev == NULL) {
941 goto fail;
942 }
943
944 info_level = (smb1cli_conn_capabilities(cli->conn) & CAP_NT_SMBS)
945 ? SMB_FIND_FILE_BOTH_DIRECTORY_INFO : SMB_FIND_EA_SIZE;
946
947 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, mask);
948
949 req = cli_list_send(frame, ev, cli, mask, attribute, info_level);
950 if (req == NULL) {
951 goto fail;
952 }
953 if (!tevent_req_poll(req, ev)) {
954 status = map_nt_error_from_unix(errno);
955 goto fail;
956 }
957
958 status = cli_list_recv(req, frame, &finfo, &num_finfo);
959 if (!NT_STATUS_IS_OK(status)) {
960 goto fail;
961 }
962
963 dircachectx = dircache_write_begin(state, num_finfo);
964
965 debuglocal(4,"list_files: got %d files\n", num_finfo);
966
967
968 for (i=0; i<num_finfo; i++) {
969 //as samba and this client have different finfo, we need to convert
970 memset(&wrpfinfo, 0, sizeof(wrpfinfo));
971 wrpfinfo.size = finfo[i].size;
972 wrpfinfo.attr = finfo[i].mode;
973 wrpfinfo.ctime = convert_timespec_to_time_t(finfo[i].ctime_ts);
974 wrpfinfo.mtime = convert_timespec_to_time_t(finfo[i].mtime_ts);
975 wrpfinfo.atime = convert_timespec_to_time_t(finfo[i].atime_ts);
976 wrpfinfo.easize = finfo[i].easize;
977 strncpy(wrpfinfo.fname, finfo[i].name, sizeof(wrpfinfo.fname) -1);
978
979 fn(cli->dfs_mountpoint, &wrpfinfo, mask, state);
980 // Also add the entry to the cache.
981 dircache_write_entry(dircachectx, &wrpfinfo);
982 }
983
984 dircache_write_end(dircachectx);
985 fail:
986 TALLOC_FREE(frame);
987 return num_finfo;
988}
989
990/*****************************************************
991open a directory on the server
992*******************************************************/
993int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
994{
995 if (!srv || !cli || !state || !*state->mask)
996 {
997 return maperror(EINVAL);
998 }
999 debuglocal(1,"Filelist <%s> on master <%s> wgrp <%s> server <%s> share <%s> clidev <%s>\n", state->mask, srv->master, srv->workgroup, srv->server_name, srv->share_name, cli->dev);
1000 if (*srv->workgroup == 0 && *srv->server_name == 0)
1001 {
1002 smbwrp_special_add(".", state);
1003 smbwrp_special_add("..", state);
1004 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
1005 smbwrp_share_add, state);
1006 } else
1007 if (*srv->server_name == 0)
1008 {
1009 smbwrp_special_add(".", state);
1010 smbwrp_special_add("..", state);
1011
1012 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
1013 smbwrp_share_add, state);
1014 } else
1015 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1016 {
1017 smbwrp_special_add(".", state);
1018 smbwrp_special_add("..", state);
1019
1020 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
1021 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
1022 {
1023 return os2cli_errno(cli);
1024 }
1025 } else
1026 if (strncmp(cli->dev,"LPT",3) == 0)
1027 {
1028 smbwrp_special_add(".", state);
1029 smbwrp_special_add("..", state);
1030 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
1031 {
1032 return os2cli_errno(cli);
1033 }
1034 }
1035 else
1036 {
1037 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1038 smbwrp_dir_add, state) < 0)
1039 {
1040 return os2cli_errno(cli);
1041 }
1042 }
1043
1044 return 0;
1045}
1046
1047/*****************************************************
1048a wrapper for chdir()
1049*******************************************************/
1050int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
1051{
1052 unsigned short mode = aDIR;
1053 smbwrp_fileinfo finfo = {0};
1054 if (!cli || !fname)
1055 {
1056 return maperror(EINVAL);
1057 }
1058
1059 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1060 if (smbwrp_getattr(srv, cli, &finfo))
1061 {
1062 return os2cli_errno(cli);
1063 }
1064
1065 if (!(finfo.attr & aDIR)) {
1066 return maperror(ENOTDIR);
1067 }
1068
1069 return 0;
1070}
1071
1072
1073/*****************************************************
1074a wrapper for mkdir()
1075*******************************************************/
1076int _System smbwrp_mkdir(cli_state * cli, char *fname)
1077{
1078 if (!cli || !fname)
1079 {
1080 return maperror(EINVAL);
1081 }
1082
1083 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname)))
1084 {
1085 return os2cli_errno(cli);
1086 }
1087 return 0;
1088}
1089
1090/*****************************************************
1091a wrapper for rmdir()
1092*******************************************************/
1093int _System smbwrp_rmdir(cli_state * cli, char *fname)
1094{
1095 if (!cli || !fname)
1096 {
1097 return maperror(EINVAL);
1098 }
1099
1100 if (!NT_STATUS_IS_OK(cli_rmdir(cli, fname)))
1101 {
1102 return os2cli_errno(cli);
1103 }
1104 return 0;
1105}
1106
1107/*****************************************************
1108set EA for a path
1109*******************************************************/
1110int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1111{
1112 if (!cli || !fname || !name)
1113 {
1114 return maperror(EINVAL);
1115 }
1116 if (!NT_STATUS_IS_OK(cli_set_ea_path(cli, fname, name, value, size)))
1117 {
1118 return os2cli_errno(cli);
1119 }
1120 return 0;
1121}
1122
1123/*****************************************************
1124set EA for a file
1125*******************************************************/
1126int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1127{
1128 if (!cli || !file || !name)
1129 {
1130 return maperror(EINVAL);
1131 }
1132 if (!NT_STATUS_IS_OK(cli_set_ea_fnum(cli, file->fd, name, value, size)))
1133 {
1134 return os2cli_errno(cli);
1135 }
1136 return 0;
1137}
1138
1139
1140#pragma pack(1)
1141typedef struct _FEA /* fea */
1142{
1143 unsigned char fEA; /* flags */
1144 unsigned char cbName; /* name length not including NULL */
1145 unsigned short cbValue; /* value length */
1146} FEA;
1147
1148typedef struct _FEALIST /* feal */
1149{
1150 unsigned long cbList; /* total bytes of structure including full list */
1151 FEA list[1]; /* variable length FEA structures */
1152} FEALIST;
1153#pragma pack()
1154
1155static int unilistea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1156{
1157 int fnum, i;
1158 int gotsize = sizeof(unsigned long);
1159 size_t num_eas;
1160 struct ea_struct *ea_list = NULL;
1161 TALLOC_CTX *mem_ctx;
1162 FEA * p;
1163 FEALIST * pfealist;
1164 char * q;
1165
1166 mem_ctx = talloc_init("%d: ealist", _gettid());
1167 pfealist = (FEALIST *)buffer;
1168 pfealist->cbList = 0;
1169
1170 if (!NT_STATUS_IS_OK(cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list)))
1171 {
1172 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1173 talloc_destroy(mem_ctx);
1174 return os2cli_errno(cli);
1175 }
1176
1177 debuglocal(4,"num_eas = %d\n", num_eas);
1178
1179 // we will count that os/2 max EA size for file is 64kb
1180 p = pfealist->list;
1181 for (i = 0; i < num_eas; i++)
1182 {
1183 int namelen = strlen(ea_list[i].name);
1184 debuglocal(4, "%d Got EA <%s> with namelen %d, size %d. Gross %d. Buf %d\n", i, ea_list[i].name, namelen, ea_list[i].value.length, gotsize, size);
1185 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1186 {
1187 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1188 continue;
1189 }
1190 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1191 if (size >= gotsize)
1192 {
1193 p->fEA = 0;
1194 p->cbName = namelen;
1195 p->cbValue = ea_list[i].value.length;
1196 q = (char *)(p + 1);
1197 strncpy(q, ea_list[i].name, namelen + 1);
1198 q += namelen + 1;
1199 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1200 p = (FEA *)(q + ea_list[i].value.length);
1201 }
1202 }
1203 pfealist->cbList = gotsize;
1204 debuglocal(4,"ret size = %d\n", gotsize);
1205
1206 talloc_destroy(mem_ctx);
1207 return 0;
1208}
1209
1210/*****************************************************
1211lists EA of a path
1212*******************************************************/
1213int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1214{
1215 if (!cli || !fname || !buffer)
1216 {
1217 return maperror(EINVAL);
1218 }
1219
1220 debuglocal(4,"EALIst for <%s>\n", fname);
1221 return unilistea(cli, fname, buffer, size);
1222}
1223
1224/*****************************************************
1225lists EA of a file
1226*******************************************************/
1227int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1228{
1229 if (!cli || !file || !buffer)
1230 {
1231 return maperror(EINVAL);
1232 }
1233
1234 debuglocal(4,"FEALIst for <%s>\n", file->fname);
1235 return unilistea(cli, file->fname, buffer, size);
1236}
1237
1238/****************************************************************************
1239Check the space on a device.
1240****************************************************************************/
1241int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1242{
1243 int total, bsize, avail;
1244
1245 if (!cli || !pfsa)
1246 {
1247 return maperror(EINVAL);
1248 }
1249
1250 if (!NT_STATUS_IS_OK(cli_dskattr(cli, &bsize, &total, &avail)))
1251 {
1252 debuglocal(4,"Error in dskattr: %s\n",cli_errstr(cli));
1253 return os2cli_errno(cli);
1254 }
1255
1256 debuglocal(4,"\n\t\t%d blocks of size %d. %d blocks available\n",
1257 total, bsize, avail);
1258
1259 // YD currently Samba return it in MB!
1260 pfsa->cSectorUnit = 1;
1261 if (bsize >= 65536)
1262 {
1263 pfsa->cUnit = total*1024;
1264 pfsa->cUnitAvail = avail*1024;
1265 pfsa->cbSector = bsize/1024;
1266 }
1267 else
1268 {
1269 pfsa->cUnit = total;
1270 pfsa->cUnitAvail = avail;
1271 pfsa->cbSector = bsize;
1272 }
1273
1274 return 0;
1275}
1276
1277/*****************************************************
1278Send an echo to the server to confirm it is still alive
1279*******************************************************/
1280int _System smbwrp_echo(cli_state * cli)
1281{
1282 debuglocal(4," smbwrp_echo\n");
1283 unsigned char garbage[16];
1284 NTSTATUS status;
1285 if (!cli)
1286 {
1287 return maperror(EINVAL);
1288 }
1289 /* Ping the server to keep the connection alive using SMBecho. */
1290 memset(garbage, 0xf0, sizeof(garbage));
1291 unsigned int old_timeout = cli->timeout;
1292 cli->timeout = 2000;// we don't want to wait 20 seconds
1293 status = cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage)));
1294 cli->timeout = old_timeout; // reset back to previous value
1295 if (NT_STATUS_IS_OK(status)) {
1296 return 0;
1297 } else {
1298 return -1;
1299 }
1300}
Note: See TracBrowser for help on using the repository browser.