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

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

Syncronise parts of smbwrp_connect based on Samba do_connect

  • Property svn:eol-style set to native
File size: 32.7 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 /* must be a normal share */
405
406 status = cli_tree_connect(c, sharename, "?????",
407 srv->password, strlen(srv->password)+1);
408 if (!NT_STATUS_IS_OK(status)) {
409 debuglocal(4,"tree connect failed: %s\n", nt_errstr(status));
410 cli_shutdown(c);
411 return status;
412 }
413
414 debuglocal(4," tconx ok.\n");
415
416 // save cli_state pointer
417 *cli = c;
418
419 return 0;
420}
421
422/*****************************************************
423close a connection to a server
424*******************************************************/
425void _System smbwrp_disconnect( Resource* pRes, cli_state * cli)
426{
427 if (pRes && cli)
428 {
429 // this call will free all buffers, close handles and free cli mem
430 cli_shutdown( cli);
431 }
432}
433
434
435
436/*****************************************************
437a wrapper for open()
438*******************************************************/
439int _System smbwrp_open(cli_state * cli, smbwrp_file * file)
440{
441 uint16_t fd = 0;
442
443 if (!cli || !file || !*file->fname)
444 {
445 return maperror(EINVAL);
446 }
447 if (file->denymode < DENY_ALL || file->denymode > DENY_NONE)
448 {
449 file->denymode = DENY_NONE;
450 }
451
452 debuglocal(4,"cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode);
453 if (!NT_STATUS_IS_OK(cli_open(cli, file->fname, file->openmode, file->denymode, &fd)))
454 {
455 return os2cli_errno(cli);
456 }
457 file->fd = fd;
458 file->updatetime = 0;
459 file->offset = 0;
460 return 0;
461}
462
463/*****************************************************
464a wrapper for read()
465*******************************************************/
466int _System smbwrp_read(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
467{
468 int ret;
469
470 if (!cli || !file || !buf || !result)
471 {
472 return maperror(EINVAL);
473 }
474 size_t nread;
475 *result = 0;
476 ret = cli_read(cli, file->fd, buf, file->offset, count, &nread);
477 if (ret == -1)
478 {
479 debuglocal(4," smbwrp_read - cli_read ret = %d\n",ret);
480 return os2cli_errno(cli);
481 }
482
483 file->offset += nread;
484 *result = nread;
485 debuglocal(4," smbwrp_read successful, nread = %d, ret = %d\n",nread,ret);
486 return 0;
487}
488
489
490
491/*****************************************************
492a wrapper for write()
493*******************************************************/
494int _System smbwrp_write(cli_state * cli, smbwrp_file * file, void *buf, unsigned long count, unsigned long * result)
495{
496 NTSTATUS status;
497 size_t ret;
498
499 if (!cli || !file || !buf || !result)
500 {
501 return maperror(EINVAL);
502 }
503
504 *result = 0;
505//debuglocal(1,("Write %x %d %lld %d", cli, file->fd, file->offset, count));
506 status = cli_writeall(cli, file->fd, 0, buf, file->offset, count, &ret);
507 if (!NT_STATUS_IS_OK(status)) {
508 return os2cli_errno(cli);
509 }
510
511 file->updatetime = 1;
512 file->offset += ret;
513 *result = ret;
514 return 0;
515}
516
517/*****************************************************
518a wrapper for close()
519*******************************************************/
520int _System smbwrp_close(cli_state * cli, smbwrp_file * file)
521{
522 int rc = 0;
523 if (!cli || !file)
524 {
525 return maperror(EINVAL);
526 }
527
528 debuglocal(4,"smpwrp_close updatetime: %d\n", file->updatetime);
529
530 if (file->updatetime == 1)
531 {
532 file->mtime = time(NULL);
533 debuglocal(4,"cli_close new mtime %lu\n", file->mtime);
534 }
535
536 if (!NT_STATUS_IS_OK(cli_close(cli, file->fd)))
537 {
538 rc = os2cli_errno(cli);
539 }
540
541 if (!rc && (file->openattr || file->mtime || file->ctime))
542 {
543 debuglocal(4,"Set pathinfo on close %s %08x %d %d\n", file->fname, file->openattr, file->mtime, file->ctime);
544 if (!NT_STATUS_IS_OK(cli_setpathinfo_basic(cli, file->fname, file->ctime, 0, file->mtime, 0, file->openattr)))
545 {
546 debuglocal(4,"Set pathinfo on close failed %d\n", os2cli_errno(cli));
547 //rc = os2cli_errno(cli);
548 }
549 }
550
551 file->openattr = 0;
552 file->mtime = 0;
553 file->ctime = 0;
554 file->updatetime = 0;
555 file->fd = -1;
556 file->offset = 0;
557 *file->fname = 0;
558 return rc;
559}
560
561int _System smbwrp_setfilesize(cli_state * cli, smbwrp_file * file, long long newsize)
562{
563 int rc = 0;
564 if (!cli || !file)
565 {
566 return maperror(EINVAL);
567 }
568
569 debuglocal(4,"cli_setnewfilesize(%s) %lld\n", file->fname, newsize);
570 if (!NT_STATUS_IS_OK(cli_ftruncate(cli, file->fd, newsize)))
571 {
572 if (newsize)
573 {
574 rc = os2cli_errno(cli);
575 }
576
577 if (!NT_STATUS_IS_OK(cli_close(cli, file->fd)))
578 {
579 return os2cli_errno(cli);
580 }
581 uint16_t fd = 0;
582 file->fd = -1;
583 file->offset = 0;
584 file->openmode &= ~(O_CREAT | O_EXCL);
585 file->openmode |= O_TRUNC;
586 debuglocal(4,"cli_setnewfileszie : cli_open(%s) attr %08x mode %02x denymode %02x\n", file->fname, file->openattr, file->openmode, file->denymode);
587 if (!NT_STATUS_IS_OK(cli_open(cli, file->fname, file->openmode, file->denymode, &fd)))
588 {
589 return os2cli_errno(cli);
590 }
591 file->fd = fd;
592 }
593 return 0;
594}
595
596/*****************************************************
597a wrapper for rename()
598*******************************************************/
599int _System smbwrp_rename(cli_state * cli, char *oldname, char *newname)
600{
601 if (!cli || !oldname || !newname)
602 {
603 return maperror(EINVAL);
604 }
605
606 debuglocal(1,"Rename <%s> -> <%s>\n", oldname, newname);
607 if (!NT_STATUS_IS_OK(cli_rename(cli, oldname, newname)))
608 {
609 return os2cli_errno(cli);
610 }
611 return 0;
612}
613
614
615/*****************************************************
616a wrapper for chmod()
617*******************************************************/
618int _System smbwrp_setattr(cli_state * cli, smbwrp_fileinfo *finfo)
619{
620 if (!cli || !finfo || !*finfo->fname)
621 {
622 return maperror(EINVAL);
623 }
624
625debuglocal(4,"Setting on <%s> attr %04x, time %lu (timezone /%lu\n", finfo->fname, finfo->attr, finfo->mtime, finfo->mtime + get_time_zone(finfo->mtime));
626 // we already have gmt time, so no need to add timezone
627 // if (!cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime + (finfo->mtime == 0 ? 0 : get_time_zone(finfo->mtime)))
628 if (!NT_STATUS_IS_OK(cli_setatr(cli, finfo->fname, finfo->attr, finfo->mtime))
629 && !NT_STATUS_IS_OK(cli_setatr(cli, finfo->fname, finfo->attr, 0)))
630 {
631 return os2cli_errno(cli);
632 }
633 return 0;
634}
635
636/*****************************************************
637a wrapper for unlink()
638*******************************************************/
639int _System smbwrp_unlink(cli_state * cli, const char *fname)
640{
641 if (!cli || !fname)
642 {
643 return maperror(EINVAL);
644 }
645#if 0
646 if (strncmp(cli->dev, "LPT", 3) == 0)
647 {
648 int job = smbw_stat_printjob(cli, fname, NULL, NULL);
649 if (job == -1)
650 {
651 goto failed;
652 }
653 if (cli_printjob_del(cli, job) != 0)
654 {
655 goto failed;
656 }
657 } else
658#endif
659 if (!NT_STATUS_IS_OK(cli_unlink(cli, fname, aSYSTEM | aHIDDEN)))
660 {
661 return os2cli_errno(cli);
662 }
663 return 0;
664}
665
666/*****************************************************
667a wrapper for lseek()
668*******************************************************/
669int _System smbwrp_lseek(cli_state * cli, smbwrp_file * file, int whence, long long offset)
670{
671 off_t size;
672 if (!cli || !file)
673 {
674 return maperror(EINVAL);
675 }
676
677 debuglocal(4,"lseek %d %lld %lld\n", whence, offset, file->offset);
678
679 switch (whence) {
680 case SEEK_SET:
681 if (offset < 0)
682 {
683 return maperror(EINVAL);
684 }
685 file->offset = offset;
686 break;
687 case SEEK_CUR:
688 file->offset += offset;
689 break;
690 case SEEK_END:
691 if (offset > 0)
692 {
693 return maperror(EINVAL);
694 }
695 if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(cli, file->fd,
696 NULL, &size, NULL, NULL, NULL,
697 NULL, NULL)) &&
698 !NT_STATUS_IS_OK(cli_getattrE(cli, file->fd,
699 NULL, &size, NULL, NULL, NULL)))
700 {
701 return os2cli_errno(cli);
702 }
703 file->offset = size + offset;
704 break;
705 default: return maperror(EINVAL);
706 }
707
708 return 0;
709}
710
711/*****************************************************
712try to do a QPATHINFO and if that fails then do a getatr
713this is needed because win95 sometimes refuses the qpathinfo
714*******************************************************/
715int _System smbwrp_getattr(smbwrp_server *srv, cli_state * cli, smbwrp_fileinfo *finfo)
716{
717 SMB_INO_T ino = 0;
718 struct timespec ctime;
719 struct timespec mtime;
720 struct timespec atime;
721
722 if (!cli || !finfo || !*finfo->fname)
723 {
724 return maperror(EINVAL);
725 }
726 debuglocal(4,"getattr %d %d <%s>\n", smb1cli_conn_capabilities(cli->conn) & CAP_NOPATHINFO2, smb1cli_conn_capabilities(cli->conn) & CAP_NT_SMBS, finfo->fname);
727
728 if (NT_STATUS_IS_OK(cli_qpathinfo2(cli, finfo->fname, &ctime, &atime, &mtime, NULL,
729 (off_t *)&finfo->size, (unsigned short *)&finfo->attr, &ino)))
730 {
731 finfo->attr &= 0x7F;
732 finfo->ctime = convert_timespec_to_time_t(ctime);
733 finfo->atime = convert_timespec_to_time_t(atime);
734 finfo->mtime = convert_timespec_to_time_t(mtime);
735 return 0;
736 }
737
738#if 0 // cli->fd not available in Samba 4.x
739 if (cli->fd == -1)
740 {
741 /* fd == -1 means the connection is broken */
742 return maperror(ENOTCONN);
743 }
744#endif
745
746 debuglocal(4, "smbwrp_getattr, calling cli_qpathinfo3\n");
747 if (NT_STATUS_IS_OK(cli_qpathinfo3(cli, finfo->fname, &ctime, &atime, &mtime, NULL,
748 (off_t *)&finfo->size, (unsigned short *)&finfo->attr, &ino)))
749 {
750 finfo->attr &= 0x7F;
751 finfo->ctime = convert_timespec_to_time_t(ctime);
752 finfo->atime = convert_timespec_to_time_t(atime);
753 finfo->mtime = convert_timespec_to_time_t(mtime);
754 return 0;
755 }
756
757 /* If the path is not on a share (it is a workgroup or a server),
758 * then cli_qpathinfo2 obviously fails. Return some fake information
759 * about the directory.
760 */
761 if ( *srv->server_name == 0
762 || (strcmp(cli->dev,"IPC") == 0)
763 || *srv->share_name == 0
764 || (stricmp(srv->share_name,"IPC$") == 0)
765 || (strncmp(cli->dev,"LPT",3) == 0)
766 )
767 {
768 debuglocal(4,"getattr not a share.\n");
769 *(time_t *)&finfo->ctime = time (NULL);
770 *(time_t *)&finfo->atime = time (NULL);
771 *(time_t *)&finfo->mtime = time (NULL);
772 finfo->size = 0;
773 finfo->easize = 0;
774 finfo->attr = aDIR;
775 return 0;
776 }
777
778 /* if this is NT then don't bother with the getatr */
779 if (smb1cli_conn_capabilities(cli->conn) & CAP_NT_SMBS/* && !(smb1cli_conn_capabilities(cli->conn) & CAP_NOPATHINFO2)*/)
780 {
781 int ret = cli_errno(cli);
782 // cli_qpathinfo* reports EINVAL when path of given file not exists
783 // thus there is no real situation when EINVAL should be returned to
784 // client at this point, we just replace it to ENOTDIR
785 if (ret == EINVAL)
786 {
787 ret = ENOTDIR;
788 }
789 return maperror(ret);
790 }
791
792 if (NT_STATUS_IS_OK(cli_getatr(cli, finfo->fname, (unsigned short *)&finfo->attr, &finfo->size, (time_t *)&finfo->mtime)))
793 {
794//debuglocal(2,("gotattr1 %08x <%s>\n", finfo->attr, finfo->fname));
795 finfo->mtime -= get_time_zone(finfo->mtime);
796 finfo->atime = finfo->atime; //was mtime
797 finfo->ctime = finfo->ctime; //was mtime
798 return 0;
799 }
800 return os2cli_errno(cli);
801}
802
803/*****************************************************
804try to do a QPATHINFO and if that fails then do a getatr
805this is needed because win95 sometimes refuses the qpathinfo
806*******************************************************/
807int _System smbwrp_fgetattr(cli_state * cli, smbwrp_file *file, smbwrp_fileinfo *finfo)
808{
809 struct timespec ctime;
810 struct timespec mtime;
811 struct timespec atime;
812 SMB_INO_T ino = 0;
813
814 if (!cli || !file || !finfo)
815 {
816 return maperror(EINVAL);
817 }
818
819 strncpy(finfo->fname, file->fname, sizeof(finfo->fname) - 1);
820 if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(cli, file->fd,
821 (unsigned short *)&finfo->attr, (off_t *)&finfo->size, &ctime, &atime, &mtime, NULL,
822 &ino)))
823 {
824 if (!NT_STATUS_IS_OK(cli_getattrE(cli, file->fd,
825 (unsigned short *)&finfo->attr, (&finfo->size), (time_t *)&finfo->ctime, (time_t *)&finfo->atime, (time_t *)&finfo->mtime)))
826 {
827 return os2cli_errno(cli);
828 }
829 else
830 {
831 finfo->ctime -= get_time_zone(finfo->ctime);
832 finfo->atime -= get_time_zone(finfo->atime);
833 finfo->mtime -= get_time_zone(finfo->mtime);
834 }
835 }
836 else
837 {
838 finfo->ctime = convert_timespec_to_time_t(ctime);
839 finfo->atime = convert_timespec_to_time_t(atime);
840 finfo->mtime = convert_timespec_to_time_t(mtime);
841 }
842
843 return 0;
844}
845
846// =============================DIRECTORY ROUTINES============================
847
848/*****************************************************
849add a entry to a directory listing
850*******************************************************/
851static NTSTATUS smbwrp_dir_add(const char* mnt, smbwrp_fileinfo *finfo, const char *mask, void *state)
852{
853 if (state && finfo)
854 {
855 filelist_state * st = (filelist_state *)state;
856 char fullname[ _MAX_PATH] = {0};
857 debuglocal(8,"adding <%s> %d %d %d\n", finfo->fname, sizeof(st->finfo), st->datalen, sizeof(st->finfo.fname));
858 memcpy(&st->finfo, finfo, sizeof(st->finfo));
859 strncpy(fullname, st->dir, strlen(st->dir));
860 strncat(fullname, finfo->fname, sizeof(fullname) - strlen(fullname) -1);
861 strncpy(st->finfo.fname, fullname, sizeof(st->finfo.fname));
862 getfindinfoL( st->pConn, st->plist, &st->finfo, st->ulAttribute, st->dir_mask);
863 }
864}
865
866static void smbwrp_special_add(const char * name, void * state)
867{
868 smbwrp_fileinfo finfo = {0};
869
870 if (!name)
871 {
872 return;
873 }
874
875 ZERO_STRUCT(finfo);
876
877 strncpy(finfo.fname, name, sizeof(finfo.fname) - 1);
878 finfo.attr = aRONLY | aDIR;
879
880 smbwrp_dir_add("", &finfo, NULL, state);
881}
882
883static NTSTATUS smbwrp_printjob_add(struct print_job_info *job, void * state)
884{
885 smbwrp_fileinfo finfo = {0};
886
887 ZERO_STRUCT(finfo);
888
889//printf("Printjob <%s>\n", job->name);
890
891 strncpy(finfo.fname, job->name, sizeof(finfo.fname) - 1);
892 finfo.mtime = job->t - get_time_zone(job->t);
893 finfo.atime = finfo.atime; //was mtime
894 finfo.ctime = finfo.ctime; //was mtime
895 finfo.attr = aRONLY;
896 finfo.size = job->size;
897
898 smbwrp_dir_add("", &finfo, NULL, state);
899}
900
901static void smbwrp_share_add(const char *share, uint32_t type,
902 const char *comment, void *state)
903{
904 smbwrp_fileinfo finfo = {0};
905
906 // strip administrative names and printers from list
907 if (type == STYPE_PRINTQ || strcmp(share,"IPC$") == 0) return;
908
909 ZERO_STRUCT(finfo);
910
911 strncpy(finfo.fname, share, sizeof(finfo.fname) - 1);
912 finfo.attr = aRONLY | aDIR;
913
914 smbwrp_dir_add("", &finfo, NULL, state);
915}
916
917/****************************************************************************
918 Do a directory listing, calling fn on each file found.
919 Modified from cli_list
920****************************************************************************/
921static int list_files(struct cli_state *cli, const char *mask, uint16_t attribute,
922 void (*fn)(const char *, smbwrp_fileinfo *, const char *,
923 void *), void *state)
924{
925 TALLOC_CTX *frame = talloc_stackframe();
926 struct event_context *ev;
927 struct tevent_req *req;
928 NTSTATUS status = NT_STATUS_NO_MEMORY;
929 struct file_info *finfo;
930 size_t i, num_finfo;
931 uint16_t info_level;
932 void *dircachectx = NULL;
933 smbwrp_fileinfo wrpfinfo;
934
935 /* Try to get the listing from cache. */
936 if (dircache_list_files(fn, state, &num_finfo))
937 {
938 /* Got from cache. */
939 return(num_finfo);
940 }
941
942 if (smbXcli_conn_has_async_calls(cli->conn)) {
943 /*
944 * Can't use sync call while an async call is in flight
945 */
946 status = NT_STATUS_INVALID_PARAMETER;
947 goto fail;
948 }
949 ev = samba_tevent_context_init(frame);
950 if (ev == NULL) {
951 goto fail;
952 }
953
954 info_level = (smb1cli_conn_capabilities(cli->conn) & CAP_NT_SMBS)
955 ? SMB_FIND_FILE_BOTH_DIRECTORY_INFO : SMB_FIND_EA_SIZE;
956
957 debuglocal(4,"list_files level %d. mask <%s>\n", info_level, mask);
958
959 req = cli_list_send(frame, ev, cli, mask, attribute, info_level);
960 if (req == NULL) {
961 goto fail;
962 }
963 if (!tevent_req_poll(req, ev)) {
964 status = map_nt_error_from_unix(errno);
965 goto fail;
966 }
967
968 status = cli_list_recv(req, frame, &finfo, &num_finfo);
969 if (!NT_STATUS_IS_OK(status)) {
970 goto fail;
971 }
972
973 dircachectx = dircache_write_begin(state, num_finfo);
974
975 debuglocal(4,"list_files: got %d files\n", num_finfo);
976
977
978 for (i=0; i<num_finfo; i++) {
979 //as samba and this client have different finfo, we need to convert
980 memset(&wrpfinfo, 0, sizeof(wrpfinfo));
981 wrpfinfo.size = finfo[i].size;
982 wrpfinfo.attr = finfo[i].mode;
983 wrpfinfo.ctime = convert_timespec_to_time_t(finfo[i].ctime_ts);
984 wrpfinfo.mtime = convert_timespec_to_time_t(finfo[i].mtime_ts);
985 wrpfinfo.atime = convert_timespec_to_time_t(finfo[i].atime_ts);
986 wrpfinfo.easize = finfo[i].easize;
987 strncpy(wrpfinfo.fname, finfo[i].name, sizeof(wrpfinfo.fname) -1);
988
989 fn(cli->dfs_mountpoint, &wrpfinfo, mask, state);
990 // Also add the entry to the cache.
991 dircache_write_entry(dircachectx, &wrpfinfo);
992 }
993
994 dircache_write_end(dircachectx);
995 fail:
996 TALLOC_FREE(frame);
997 return num_finfo;
998}
999
1000/*****************************************************
1001open a directory on the server
1002*******************************************************/
1003int _System smbwrp_filelist(smbwrp_server *srv, cli_state * cli, filelist_state * state)
1004{
1005 if (!srv || !cli || !state || !*state->mask)
1006 {
1007 return maperror(EINVAL);
1008 }
1009 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);
1010 if (*srv->workgroup == 0 && *srv->server_name == 0)
1011 {
1012 smbwrp_special_add(".", state);
1013 smbwrp_special_add("..", state);
1014 cli_NetServerEnum(cli, srv->master, SV_TYPE_DOMAIN_ENUM,
1015 smbwrp_share_add, state);
1016 } else
1017 if (*srv->server_name == 0)
1018 {
1019 smbwrp_special_add(".", state);
1020 smbwrp_special_add("..", state);
1021
1022 cli_NetServerEnum(cli, srv->workgroup, SV_TYPE_ALL,
1023 smbwrp_share_add, state);
1024 } else
1025 if ((strcmp(cli->dev,"IPC") == 0) || *srv->share_name == 0 || (stricmp(srv->share_name,"IPC$") == 0))
1026 {
1027 smbwrp_special_add(".", state);
1028 smbwrp_special_add("..", state);
1029
1030 if (net_share_enum_rpc(cli, smbwrp_share_add, state) < 0 &&
1031 cli_RNetShareEnum(cli,smbwrp_share_add, state) < 0)
1032 {
1033 return os2cli_errno(cli);
1034 }
1035 } else
1036 if (strncmp(cli->dev,"LPT",3) == 0)
1037 {
1038 smbwrp_special_add(".", state);
1039 smbwrp_special_add("..", state);
1040 if (cli_print_queue_state(cli, smbwrp_printjob_add, state) < 0)
1041 {
1042 return os2cli_errno(cli);
1043 }
1044 }
1045 else
1046 {
1047 if (list_files(cli, state->mask, aHIDDEN|aSYSTEM|aDIR,
1048 smbwrp_dir_add, state) < 0)
1049 {
1050 return os2cli_errno(cli);
1051 }
1052 }
1053
1054 return 0;
1055}
1056
1057/*****************************************************
1058a wrapper for chdir()
1059*******************************************************/
1060int _System smbwrp_chdir(smbwrp_server *srv, cli_state * cli, char *fname)
1061{
1062 unsigned short mode = aDIR;
1063 smbwrp_fileinfo finfo = {0};
1064 if (!cli || !fname)
1065 {
1066 return maperror(EINVAL);
1067 }
1068
1069 strncpy(finfo.fname, fname, sizeof(finfo.fname) - 1);
1070 if (smbwrp_getattr(srv, cli, &finfo))
1071 {
1072 return os2cli_errno(cli);
1073 }
1074
1075 if (!(finfo.attr & aDIR)) {
1076 return maperror(ENOTDIR);
1077 }
1078
1079 return 0;
1080}
1081
1082
1083/*****************************************************
1084a wrapper for mkdir()
1085*******************************************************/
1086int _System smbwrp_mkdir(cli_state * cli, char *fname)
1087{
1088 if (!cli || !fname)
1089 {
1090 return maperror(EINVAL);
1091 }
1092
1093 if (!NT_STATUS_IS_OK(cli_mkdir(cli, fname)))
1094 {
1095 return os2cli_errno(cli);
1096 }
1097 return 0;
1098}
1099
1100/*****************************************************
1101a wrapper for rmdir()
1102*******************************************************/
1103int _System smbwrp_rmdir(cli_state * cli, char *fname)
1104{
1105 if (!cli || !fname)
1106 {
1107 return maperror(EINVAL);
1108 }
1109
1110 if (!NT_STATUS_IS_OK(cli_rmdir(cli, fname)))
1111 {
1112 return os2cli_errno(cli);
1113 }
1114 return 0;
1115}
1116
1117/*****************************************************
1118set EA for a path
1119*******************************************************/
1120int _System smbwrp_setea(cli_state * cli, char *fname, char * name, unsigned char * value, int size)
1121{
1122 if (!cli || !fname || !name)
1123 {
1124 return maperror(EINVAL);
1125 }
1126 if (!NT_STATUS_IS_OK(cli_set_ea_path(cli, fname, name, value, size)))
1127 {
1128 return os2cli_errno(cli);
1129 }
1130 return 0;
1131}
1132
1133/*****************************************************
1134set EA for a file
1135*******************************************************/
1136int _System smbwrp_fsetea(cli_state * cli, smbwrp_file *file, char * name, unsigned char * value, int size)
1137{
1138 if (!cli || !file || !name)
1139 {
1140 return maperror(EINVAL);
1141 }
1142 if (!NT_STATUS_IS_OK(cli_set_ea_fnum(cli, file->fd, name, value, size)))
1143 {
1144 return os2cli_errno(cli);
1145 }
1146 return 0;
1147}
1148
1149
1150#pragma pack(1)
1151typedef struct _FEA /* fea */
1152{
1153 unsigned char fEA; /* flags */
1154 unsigned char cbName; /* name length not including NULL */
1155 unsigned short cbValue; /* value length */
1156} FEA;
1157
1158typedef struct _FEALIST /* feal */
1159{
1160 unsigned long cbList; /* total bytes of structure including full list */
1161 FEA list[1]; /* variable length FEA structures */
1162} FEALIST;
1163#pragma pack()
1164
1165static int unilistea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1166{
1167 int fnum, i;
1168 int gotsize = sizeof(unsigned long);
1169 size_t num_eas;
1170 struct ea_struct *ea_list = NULL;
1171 TALLOC_CTX *mem_ctx;
1172 FEA * p;
1173 FEALIST * pfealist;
1174 char * q;
1175
1176 mem_ctx = talloc_init("%d: ealist", _gettid());
1177 pfealist = (FEALIST *)buffer;
1178 pfealist->cbList = 0;
1179
1180 if (!NT_STATUS_IS_OK(cli_get_ea_list_path(cli, fname, mem_ctx, &num_eas, &ea_list)))
1181 {
1182 debuglocal(4,"ea_get_file list failed - %s\n", cli_errstr(cli));
1183 talloc_destroy(mem_ctx);
1184 return os2cli_errno(cli);
1185 }
1186
1187 debuglocal(4,"num_eas = %d\n", num_eas);
1188
1189 // we will count that os/2 max EA size for file is 64kb
1190 p = pfealist->list;
1191 for (i = 0; i < num_eas; i++)
1192 {
1193 int namelen = strlen(ea_list[i].name);
1194 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);
1195 if (namelen > 0xFF || ea_list[i].value.length > 0xFFFF)
1196 {
1197 debuglocal(4, "Skip EA <%s> with namelen %d, size %d\n", ea_list[i].name, namelen, ea_list[i].value.length);
1198 continue;
1199 }
1200 gotsize += sizeof(FEA) + namelen + ea_list[i].value.length + 1;
1201 if (size >= gotsize)
1202 {
1203 p->fEA = 0;
1204 p->cbName = namelen;
1205 p->cbValue = ea_list[i].value.length;
1206 q = (char *)(p + 1);
1207 strncpy(q, ea_list[i].name, namelen + 1);
1208 q += namelen + 1;
1209 memcpy(q, ea_list[i].value.data, ea_list[i].value.length);
1210 p = (FEA *)(q + ea_list[i].value.length);
1211 }
1212 }
1213 pfealist->cbList = gotsize;
1214 debuglocal(4,"ret size = %d\n", gotsize);
1215
1216 talloc_destroy(mem_ctx);
1217 return 0;
1218}
1219
1220/*****************************************************
1221lists EA of a path
1222*******************************************************/
1223int _System smbwrp_listea(cli_state * cli, char *fname, void * buffer, unsigned long size)
1224{
1225 if (!cli || !fname || !buffer)
1226 {
1227 return maperror(EINVAL);
1228 }
1229
1230 debuglocal(4,"EALIst for <%s>\n", fname);
1231 return unilistea(cli, fname, buffer, size);
1232}
1233
1234/*****************************************************
1235lists EA of a file
1236*******************************************************/
1237int _System smbwrp_flistea(cli_state * cli, smbwrp_file *file, void * buffer, unsigned long size)
1238{
1239 if (!cli || !file || !buffer)
1240 {
1241 return maperror(EINVAL);
1242 }
1243
1244 debuglocal(4,"FEALIst for <%s>\n", file->fname);
1245 return unilistea(cli, file->fname, buffer, size);
1246}
1247
1248/****************************************************************************
1249Check the space on a device.
1250****************************************************************************/
1251int _System smbwrp_dskattr(cli_state * cli, FSALLOCATE *pfsa)
1252{
1253 int total, bsize, avail;
1254
1255 if (!cli || !pfsa)
1256 {
1257 return maperror(EINVAL);
1258 }
1259
1260 if (!NT_STATUS_IS_OK(cli_dskattr(cli, &bsize, &total, &avail)))
1261 {
1262 debuglocal(4,"Error in dskattr: %s\n",cli_errstr(cli));
1263 return os2cli_errno(cli);
1264 }
1265
1266 debuglocal(4,"\n\t\t%d blocks of size %d. %d blocks available\n",
1267 total, bsize, avail);
1268
1269 // YD currently Samba return it in MB!
1270 pfsa->cSectorUnit = 1;
1271 if (bsize >= 65536)
1272 {
1273 pfsa->cUnit = total*1024;
1274 pfsa->cUnitAvail = avail*1024;
1275 pfsa->cbSector = bsize/1024;
1276 }
1277 else
1278 {
1279 pfsa->cUnit = total;
1280 pfsa->cUnitAvail = avail;
1281 pfsa->cbSector = bsize;
1282 }
1283
1284 return 0;
1285}
1286
1287/*****************************************************
1288Send an echo to the server to confirm it is still alive
1289*******************************************************/
1290int _System smbwrp_echo(cli_state * cli)
1291{
1292 debuglocal(4," smbwrp_echo\n");
1293 unsigned char garbage[16];
1294 NTSTATUS status;
1295 if (!cli)
1296 {
1297 return maperror(EINVAL);
1298 }
1299 /* Ping the server to keep the connection alive using SMBecho. */
1300 memset(garbage, 0xf0, sizeof(garbage));
1301 unsigned int old_timeout = cli->timeout;
1302 cli->timeout = 2000;// we don't want to wait 20 seconds
1303 status = cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage)));
1304 cli->timeout = old_timeout; // reset back to previous value
1305 if (NT_STATUS_IS_OK(status)) {
1306 return 0;
1307 } else {
1308 return -1;
1309 }
1310}
Note: See TracBrowser for help on using the repository browser.